给一个森林,询问某两点之间的路径长度。
由于所给图不存在父子关系,因此根据输入建立无向边。任选一个未访问的顶点作为某棵树的根节点开始进行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;
}