[USACO Oct08] 牧场旅行
倍增,Tarjan,树剖。
我选择树剖。
// q.c #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int M=1000+10; /***********************************************************************/ struct Edge { int u,v,nex,val; Edge() {} Edge(int a,int b,int c,int d):u(a),v(b),nex(c),val(d) {} }ed[M<<1]; int head[M],cnt; void add_edge(int a,int b,int c) { ed[cnt]=Edge(a,b,head[a],c); head[a]=cnt++; ed[cnt]=Edge(b,a,head[b],c); head[b]=cnt++; } /***********************************************************************/ int dep[M],size[M],son[M],f[M],dis[M]; void dfs1(int u,int fa,int d,int ds) { f[u]=fa; dep[u]=d; size[u]=1; dis[u]=ds; int i; Edge e; for(i=head[u];~i;i=ed[i].nex) { e=ed[i]; if(!f[e.v]) { dfs1(e.v,u,d+1,ds+e.val); size[u]+=size[e.v]; if(size[e.v]>size[son[u]]||!son[u]) son[u]=e.v; } } } int top[M]; void dfs2(int u,int TP) { top[u]=TP; if(!son[u]) return ; dfs2(son[u],TP); int i; Edge e; for(i=head[u];~i;i=ed[i].nex) { e=ed[i]; if(e.v!=f[u]&&e.v!=son[u]) dfs2(e.v,e.v); } } int lca(int a,int b) { while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) swap(a,b); a=f[top[a]]; } return dep[a]<dep[b]?a:b; } /***********************************************************************/ int main() { freopen("pwalk.in","r",stdin); freopen("pwalk.out","w",stdout); int n,q,a,b,c; scanf("%d%d",&n,&q); memset(head,-1,sizeof(head)); for(int i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&c); add_edge(a,b,c); } dfs1(1,-1,0,0); dfs2(1,1); for(int i=1;i<=q;i++) { scanf("%d%d",&a,&b); c=lca(a,b); printf("%d\n",dis[a]+dis[b]-(dis[c]<<1)); } return 0; }