UVLive 5061 LCA

题意:一棵树,给你很多对点以及一个值,在这两点路径上的点的值增加那么多,问最后所有点的值。

思路:对于两个点,找他们的最近刚刚祖先,然后他们到最近公共祖先的路径上的所有点值增加,这里离线处理,并查集时注意不能压缩路径。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
int m,n;
int fst[105555],next[211111],node[211111],en;
bool vis[105555];
int ans[105555];
int f[105555];
int t;
struct qq
{
    int v;
    int val;
};
vector<qq>d[105555];
vector<qq>g[105555];
void init()
{
    en=0;
    memset(fst,-1,sizeof(fst));
    memset(vis,0,sizeof(vis));
    memset(ans,0,sizeof(ans));
    for(int i=0;i<n;i++)
    {
        g[i].clear();
        d[i].clear();
        f[i]=i;
    }
}
void add(int u,int v)
{
    next[en]=fst[u];
    fst[u]=en;
    node[en]=v;
    en++;
}
int find(int x)
{
    if(f[x]==x)return x;
    else return find(f[x]);
}
void ad(int v,int r,int va)
{
    if(v==r)return;
    ans[v]+=va;
    ad(f[v],r,va);
}
void tarjan(int u,int r)
{
    for(int i=fst[u];i!=-1;i=next[i])
    {
        int v=node[i];
        if(v!=r)tarjan(v,u);
    }
    int size=g[u].size();
    for(int i=0;i<size;i++)
    {
        qq te=g[u][i];
        if(vis[te.v])
        {
            int rot=find(te.v);
            ad(te.v,rot,te.val);
            ans[rot]+=te.val;
            qq tte;
            tte.v=u;
            tte.val=te.val;
            d[rot].push_back(tte);
        }
    }
    f[u]=r;
    vis[u]=1;
    int ss=d[u].size();
    for(int i=0;i<ss;i++)
    {
        qq te=d[u][i];
        ad(te.v,u,te.val);
    }
}
int main()
{
    int ca=1;
    int u,v,va;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        init();
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&u,&v,&va);
            if(u==v)
            {
                ans[u]+=va;
                continue;
            }
            qq te;
            te.v=u;
            te.val=va;
            g[v].push_back(te);
            te.v=v;
            g[u].push_back(te);
        }
        tarjan(0,0);
        cout<<"Case #"<<ca++<<":"<<endl;
        for(int i=0;i<n;i++)cout<<ans[i]<<endl;
    }
    return 0;
}


你可能感兴趣的:(LCA,Baoge)