Hdu 2874 Connections between cities
题意:
城市 道路 没有环 不一定连通的树 求两城市的最短距离 设想一下就是很多小树 那好办
思路:
lca离线算法 然后有个技巧就是 每次我们tarjan一棵树不是最后树的节点都访问过并且孩子全能找到老爸嘛 那么我们只要做做做做 做到全部的城市都访问过了 就行了 反正你做这颗小树的时候又不会影响到其他树的
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int n,m; const int N = 10005; const int M = 1000005; int f[N],Next[2*N],va[2*N],wi[2*N],Head[N]; int vis[N]; int nex[2*M],to[2*M],id[M],head[N],ans[M]; int find(int x) { if(x!=f[x])f[x]=find(f[x]); return f[x]; } int len,dis[N],l; void add(int u,int v,int w) { va[len]=v; wi[len]=w; Next[len]=Head[u]; Head[u]=len++; } void add_x(int u,int v) { to[l]=v; nex[l]=head[u]; head[u]=l++; } void lca(int u,int fa) { f[u]=u; for(int i=Head[u];i!=-1;i=Next[i]) {int v=va[i],w=wi[i]; if(v!=fa){ dis[v]=dis[u]+w; lca(v,u); f[v]=u; } } vis[u]=1; for(int i=head[u];i!=-1;i=nex[i]) { int v=to[i]; if(vis[v]) {//puts("sadasd"); ans[i/2]=find(v); } } } int main() { int k; while(~scanf("%d%d%d",&n,&m,&k)) { len=l=0; memset(Head,-1,sizeof Head); memset(head,-1,sizeof head); for(int i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); } dis[1]=0; for(int i=0;i<k;i++) { int u,v; scanf("%d%d",&u,&v); id[i]=u; add_x(u,v); add_x(v,u); } memset(vis,0,sizeof vis); memset(f,0,sizeof f); memset(ans,-1,sizeof ans); for(int i=1;i<=n;i++)if(vis[i]==0)lca(i,0); for(int i=0;i<l;i+=2) { int a,b,c; a=to[i]; b=id[i/2]; if(find(a)!=find(b))puts("Not connected"); else {c=ans[i/2]; printf("%d\n",dis[a]+dis[b]-2*dis[c]);} } } }