一,首先就是比较简单(弱智的我看了将近半小时)的tarjan了;我一直在纠结于一个地方就是如果要求的是8和5的话我一直以为他求出来的最近公共祖先是1...但不是,因为8和5都属于2,在遍历2的时候就求出来了,同理要是求8和9的话在遍历4的时候也都求出来了。这一步我想了很久真的怀疑自己的智商。不过至少看懂了。。。

 

hdu2586:

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
const int nmax=40005;
vector<int>v[nmax],w[nmax],q[nmax],c[nmax];
int f[nmax],d[nmax],ans[nmax],vis[nmax];
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}
int Union(int x,int y){
    int p=find(x);
    int q=find(y);
    if(p!=q) f[y]=x;
}
int read(){
    int x=0;
    char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return x;
}
void tarjan(int cur,int val){
    vis[cur]=1;
    d[cur]=val;
    for(int i=0;i<v[cur].size();i++){
        int tmp=v[cur][i];
        if(vis[tmp]) continue;
        tarjan(tmp,val+w[cur][i]);
        Union(cur,tmp);
    }
    for(int i=0;i<q[cur].size();i++){
        int tmp=q[cur][i];
        if(vis[tmp]){
            ans[c[cur][i]]=d[cur]+d[tmp]-2*d[find(tmp)];
        }
    }
}
int main(){
    int cnt;
    cnt=read();
    while(cnt--){
        int n=read(),m=read();
        rep(i,n){
            v[i].clear();
            w[i].clear();
            q[i].clear();
            c[i].clear();
            f[i]=i;
            vis[i]=0;
            d[i]=0;
        }
        rep(i,n-1){
            int u=read(),o=read(),e=read();
            v[u].push_back(o);
            w[u].push_back(e);
            v[o].push_back(u);
            w[o].push_back(e);
        }
        rep(i,m){
            int o=read(),e=read();
            q[o].push_back(e);
            q[e].push_back(o);
            c[o].push_back(i);
            c[e].push_back(i);
        }
        tarjan(1,0);
        rep(i,m)
          printf("%d\n",ans[i]);
    }
    return 0;
}