6
题意:给出一些树:有n(10000), m条边(10000), c(1000000)个询问,每个询问a b要求找到a到b的最短距离,如果ab不在同一棵树,输出-1.
LCA 离线算法;
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=10012;//node const int maxm=2222252;//query int n,m,c,head1[maxn],head2[maxn],dis[maxn],vis[maxn],fa[maxn],ans[maxm],id[maxn],num,cnt; struct node { int en,len,next; }E[maxm],Q[maxm]; void add1(int st,int en,int len ) { E[num].en=en,E[num].len=len,E[num].next=head1[st]; head1[st]=num++; } void add2(int st,int en,int len) { Q[num].en=en,Q[num].len=len,Q[num].next=head2[st]; head2[st]=num++; } int find(int x) { if(fa[x]==x) return fa[x]; else return fa[x]=find(fa[x]); } void dfs(int u) { id[u]=cnt; vis[u] = 1; fa[u] = u; for (int i = head2[u];i!=-1; i=Q[i].next) { int v=Q[i].en; if(vis[v]){ if(id[u]==id[v])//判断是否在同一棵树下 { ans[Q[i].len]=dis[u]+dis[v]-2*dis[find(v)]; }else ans[Q[i].len]=-1; } } for(int i= head1[u];i!=-1;i=E[i].next) { int v=E[i].en; if(!vis[v]){ dis[v] = dis[u] + E[i].len; dfs(v); fa[v] = u; } } } int main() { int i,j,u,v,d; while(scanf("%d%d%d",&n,&m,&c)!=EOF) { for(i=1;i<=n;i++)fa[i]=0,ans[i]=id[i]=vis[i]=0,head1[i]=head2[i]=-1; for(num=0,i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&d); add1(u,v,d); add1(v,u,d); } for(num=0,i=1;i<=c;i++) { scanf("%d%d",&u,&v); add2(u,v,i); add2(v,u,i); } for(cnt=i=1;i<=n;i++,cnt++) { if(!vis[i]) { dis[i]=0; dfs(i); } } for(i=1;i<=c;i++) { if(ans[i]>=0) { printf("%d\n",ans[i]); } else printf("Not connected\n"); } } return 0; }