您的位置:首页 > 其它

LCA-并查集+tarjan-poj2874

2017-01-20 19:50 423 查看
要先加距离再回溯,多组数据是真的坑。

题意:给你N个点、M条无向边以及边的长度,可能这些点和边构成的不是一棵树,而是森林。然后给出Q次查询,查询两个节点间的最短距离。

#include<stdio.h>
#include<stdlib.h>
struct node{
int to,next,w;
}a[20010];
struct node1{
int to,next,ans;
}b[2000010];
int top,jl[10010],begin[10010],wenti[10010];
int fa[10010],p[10010],pd[10010],bh[10010];
void add(int x,int y,int w){
a[++top].to=y;
a[top].w=w;
a[top].next=begin[x];
begin[x]=top;
return;
}
int findfa(int x)
{
if(fa[x]==x) return x;
return fa[x]=findfa(fa[x]);
}
void findans(int x,int y,int k){
int lca=findfa(y);
b[k].ans=jl[x] + jl[y] - 2*jl[lca];
return;
}
void dfs(int d){

p[d]=1;
fa[d]=d;
int h=wenti[d];
while(h){
if(fa[b[h].to]==b[h].to){
b[h].ans=jl[d] - jl[b[h].to];
}
else if(fa[b[h].to]!=0){
findans(d,b[h].to,h);
}
h=b[h].next;
}
h=begin[d];
while(h){
if(! p[a[h].to]){
dfs(a[h].to);
fa[a[h].to]=d;
}
h=a[h].next;
}
return;
}
void dfs1(int d){
bh[d]=top;
int h=begin[d];
while(h){
if(bh[a[h].to]==0){
jl[a[h].to]=jl[d]+a[h].w;
dfs1(a[h].to);
}
h=a[h].next;
}
return;
}
int main(){
int n,m,x,y,w,i,j,k;
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
for(i=1;i<=10000;i++){
begin[i]=0;
wenti[i]=0;
bh[i]=0;
pd[i]=0;
p[i]=0;
jl[i]=0;
fa[i]=0;
}
top=0;
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
add(y,x,w);
}
top=0;
for(i=1;i<=n;i++){
if(bh[i]==0){
top++;
dfs1(i);
}
}
top=0;
for(i=1;i<=k;i++){
scanf("%d%d",&x,&y);
if(x==y){
b[++top].ans=0;
b[++top].ans=-2;
}
else if(bh[x]!=bh[y]){
b[++top].ans=-1;
b[++top].ans=-2;
}

else {
b[++top].to=y;
b[top].ans=-2;
b[top].next=wenti[x];
wenti[x]=top;
b[++top].to=x;
b[top].ans=-2;
b[top].next=wenti[y];
wenti[y]=top;
}
}
for(i=1;i<=n;i++){
if(pd[bh[i]]==0){
dfs(i);
pd[bh[i]]=1;
}
}
for(i=1;i<=2*k;i++){
if(b[i].ans==-2)
continue;
if(b[i].ans==-1)
printf("Not connected\n");
else
printf("%d\n",b[i].ans);
}
}

return 0;
}
/*
5 3 3
1 3 2
2 4 3
5 2 3
1 4
4 5
1 1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LCA