HDU2874 Connections between cities 最近公共祖先

时间:2022-05-25 16:55:43

第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先。因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟,可以先将u,v,和其最近公共祖先保存到数组,然后再求结果,为什么不能直接保存其结果了。如果只保存结果的话,保存查询操作就可以节约1/3的内存,所以基本可以过了。

代码如下:

方法一:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 10100;
vector<pair<int,int> >tree[maxn],query[maxn];
int father[2][maxn],res[1000010],dis[maxn],vis[maxn]; void init(int n)
{
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
memset(res,-1,sizeof(res));
for( int i = 0; i <= n; i++){
tree[i].clear();
query[i].clear();
father[0][i] = father[1][i] = i;
}
}
int find(int x,int k){
if( x != father[k][x])
return father[k][x] = find(father[k][x],k);
return father[k][x];
}
void LCA(int u){
vis[u] = 1; pair<int,int>x;
int i,size = query[u].size();
for( i = 0; i < size; i++){
x = query[u][i];
if( vis[x.first])
res[x.second] = dis[u] + dis[x.first] - 2*dis[find(x.first,0)];
} size = tree[u].size();
for( i = 0; i < size; i++){
x = tree[u][i];
if( !vis[x.first] ){
dis[x.first] = dis[u] + x.second;
LCA(x.first);
union_set(x.first,u,0);
}
}
}
void union_set(int x,int y,int k){
x = find(x,k);
y = find(y,k);
if ( x != y)
father[k][x] = father[k][y];
}
int main()
{
int n,m,c;
int u,v,d;
int i;
// freopen("in.txt","r",stdin);
while( ~scanf("%d%d%d",&n,&m,&c) ){
init(n);
while( m-- ){
scanf("%d%d%d",&u,&v,&d);
union_set(u,v);
tree[u].push_back(make_pair(v,d));
tree[v].push_back(make_pair(u,d));
}
for( i = 0; i < c; i++){
scanf("%d%d",&u,&v);
if( find(u,1) != find(v,1))continue;
query[u].push_back(make_pair(v,i));
query[v].push_back(make_pair(u,i));
}
for( i = 1; i <= n; i++){
if( !vis[i] )
LCA(i);
}
for( i = 0; i < c; i++)
if( res[i] == -1)puts("Not connected");
else printf("%d\n",res[i]);
}
return 0;
}

方法二:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm> using namespace std;
const int maxn = 10100;
int anc[maxn],dis[maxn],deep[maxn],vis[maxn],fa[maxn];
vector<pair<int,int> >tree[maxn];
void init(int n)
{
memset(vis,0,sizeof(vis));
for( int i = 1; i <= n; i++){
fa[i] = i;
tree[i].clear();
}
}
void dfs(int u,int now_fa,int now_anc,int now_deep,int now_len)
{
fa[u] = now_fa;
anc[u] = now_anc;
vis[u] = u;
deep[u] = now_deep;
dis[u] = now_len;
for( int i = 0; i < tree[u].size() ; i++)
{
pair<int,int>x = tree[u][i];
if( !vis[x.first] )
dfs(x.first,u,now_anc,now_deep+1,now_len+x.second);
}
}
int find(int x,int y){
if( x == y)return x;
if( deep[x] > deep[y])
return find(fa[x],y);
else return find(x,fa[y]);
}
int main()
{
int n,m,c;
int u,v,d;
int i;
while( ~scanf("%d%d%d",&n,&m,&c)){
init(n); while( m-- ){
scanf("%d%d%d",&u,&v,&d);
tree[u].push_back(make_pair(v,d));
tree[v].push_back(make_pair(u,d));
}
for( i = 1; i <= n; i++ )
if(!vis[i])
dfs(i,-1,i,0,0);
for( i = 0; i < c; i++){
scanf("%d%d",&u,&v);
if(anc[u] != anc[v])puts("Not connected");
else printf("%d\n",dis[u]+dis[v] - 2*dis[find(u,v)]);
}
}
return 0;
}