标签:
题目链接:
Time Limit: 10000/5000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
/* 2874 1731MS 29448K 2286 B G++ 2014300227 */ #include <bits/stdc++.h> using namespace std; const int N=1e4+4; typedef long long ll; const double PI=acos(-1.0); int n,m,c,cnt,head[N],a,b,num,pre[N],p[N],l,r,v,dis[N],ans[1000005],vis[N],fa[N]; struct Edge { int to,va,next; }; Edge edge[2*N]; struct ques { int to,next,id; }; ques que[2000000+20]; void add(int s,int e,int v) { //edge[cnt].fr = s; edge[cnt].to = e; edge[cnt].va=v; edge[cnt].next = head[s]; head[s] = cnt++;//学会了这种存边的方法; } void q_add(int s,int e,int order) { //que[num].fr = s; que[num].to = e; que[num].next = pre[s]; que[num].id=order; pre[s] = num++; } int findset(int x) { if(x == p[x])return x; return p[x] = findset(p[x]); } int fun(int x) { if(x==fa[x])return x; return fa[x]=fun(fa[x]); } void Tarjan(int x,int dist) { vis[x] = 1; dis[x]=dist; for(int i = head[x];i!=-1;i = edge[i].next)//head[x]指向以x为端点的一条边;下面的pre[x]也是相同的道理; { int y = edge[i].to; if(!vis[y]) { Tarjan(y,dist+edge[i].va); fa[y] = x; } }//前边表示这个节点的所有子树已经处理完毕,下面可以回答相关的询问了; for(int i = pre[x];i!=-1;i = que[i].next) { int y = que[i].to; if(findset(x) == findset(y)) { if(vis[y]) ans[que[i].id] = dis[y]+dis[x]-2*dis[fun(y)]; } else ans[que[i].id] = -1; } } int main() { while(scanf("%d%d%d",&n,&m,&c)!=EOF) { for(int i = 0;i <= n;i++) { p[i] = i; fa[i] = i; head[i]=pre[i]=-1; vis[i]=0; } cnt = 0; num = 0; for(int i = 0;i < m;i++) { scanf("%d%d%d",&l,&r,&v); int fx=findset(l),fy=findset(r); if(fx!=fy)p[fx]=fy;//看是否在一个树上的并查集 add(l,r,v); add(r,l,v); } for(int i = 0;i < c;i++) { scanf("%d%d",&a,&b); q_add(a,b,i); q_add(b,a,i); } for(int i=1;i<=n;i++) { if(!vis[i]) { Tarjan(i,0); } } for(int i = 0;i < c;i++) { if(ans[i]>-1)printf("%d\n",ans[i]); else printf("Not connected\n"); } } return 0; }
hdu-2874 Connections between cities(lca+tarjan+并查集)
标签:
原文地址:http://www.cnblogs.com/zhangchengc919/p/5376560.html