Codevs 2370 小机房的树

传送
LCA的应用。
用Tarjan的方法来找最近公共祖先,dfs过程中求出当前节点到根节点的距离。
那么ans=dep[u]-dep[lca]+dep[v]-dep[lca];

#include
#include
#include
#include
#define LL long long 
#define M 750009 
using namespace std;
int head[M],to[2*M],nxt[2*M],tt,cost[2*M];
int qhead[M],qto[2*M],qnxt[2*M],qtt,lca[2*M],dep[2*M];
int f[M];
int n,m,root;
bool vis[M];
void add(int x,int y,int z)
{
    to[++tt]=y;
    nxt[tt]=head[x];
    head[x]=tt;
    cost[tt]=z;
}
void qadd(int x,int y)
{
    qto[++qtt]=y;
    qnxt[qtt]=qhead[x];
    qhead[x]=qtt;
}
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]); 
}
void dfs(int x)
{
    f[x]=x;
    vis[x]=1;
    for(int i=head[x];i;i=nxt[i])
    if(!vis[to[i]])
    {
        dep[to[i]]=dep[x]+cost[i];
        dfs(to[i]);
        f[to[i]]=x;
    }
    for(int i=qhead[x];i;i=qnxt[i])
    if(vis[qto[i]])
    {
        lca[i]=find(qto[i]);
        if(i%2) lca[i+1]=lca[i];
        else lca[i-1]=lca[i];
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;iint x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        qadd(x,y);qadd(y,x);
    }
    root=0;
    dfs(root);

    for(int i=1;i<=m;i++)
    {
        int ans=dep[qto[2*i]]-dep[lca[2*i]]+dep[qto[2*i-1]]-dep[lca[2*i]];
        printf("%d\n",ans);
    }

    return 0;
}

你可能感兴趣的:(dfs,模板,LCA,Tarjan)