给一个森林,询问某两点之间的路径长度。
由于所给图不存在父子关系,因此根据输入建立无向边。任选一个未访问的顶点作为某棵树的根节点开始进行DFS,注意DFS前vis数组必须清0。
为什么选择前向星?因为用vector邻接表会爆内存。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<stack> #include<cmath> #include<queue> #include<vector> using namespace std; #define maxn 10001 struct Edge{ int to,next,w; }edge[20001]; struct Querry{ int to,next; }Q[2000001]; int cnt,cnt2,head[maxn],head2[maxn]; bool vis[maxn],V[maxn]; int fa[maxn],ans[1000001],d[maxn]; int Find(int x) { if(fa[x]==x) return x; return fa[x]=Find(fa[x]); } void Union(int x,int y) { x=Find(x); y=Find(y); if(x==y) return; fa[y]=x; } inline void add(int u,int v,int w) { edge[cnt].to=v; edge[cnt].next=head[u]; edge[cnt].w=w; head[u]=cnt++; } inline void add(int u,int v) { Q[cnt2].to=v; Q[cnt2].next=head2[u]; head2[u]=cnt2++; } void dfs(int u,int w) { vis[u]=1,d[u]=w,V[u]=1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(vis[v]) continue; dfs(v,w+edge[i].w); Union(u,v); } for(int i=head2[u];~i;i=Q[i].next) { int v=Q[i].to; if(!vis[v]) continue; ans[i>>1]=d[u]+d[v]-(d[Find(v)]<<1); } } int main() { int n,i,u,v,w,q,m; while(~scanf("%d%d%d",&n,&m,&q)) { for(i=0;i<=n;++i){ head[i]=-1; head2[i]=-1; d[i]=0; fa[i]=i; V[i]=0; } cnt=cnt2=0; memset(ans,-1,sizeof(ans)); for(i=0;i<m;++i) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } for(i=0;i<q;++i) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;++i) if(!V[i]){ memset(vis,0,sizeof(vis)); dfs(i,0); } for(i=0;i<q;++i) { if(ans[i]!=-1) printf("%d\n",ans[i]); else printf("Not connected\n"); } } return 0; }