CodeForces - 191C - Fools and Roads (LCA)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40032278/article/details/81539251

http://codeforces.com/problemset/problem/191/C

题目

给出一棵n个节点的树,还有树上的k条简单路径(用路径的两个端点u和v表示),求树上的各条边被这些简单路径经过的总次数。

题解

只要记录一下每个节点i到根节点路径上所有边都需要加的权值sum[i]就行了。
对于每一组(u,v),题意操作转化为 c[u]++ , a[v]++ , a[ lca(u,v) ] - =2。
最后用一遍dfs把sum拆开

#include<bits/stdc++.h>
using namespace std;
int to[400010],h1[400010],h2[400010],cnt,next[400010];
int f[400010],a[400010],c[400010];
void add(int head[],int u,int vv)
{
    cnt++;
    to[cnt]=vv;
    next[cnt]=head[u];
    head[u]=cnt;
}
int find(int x)
{
    return x==f[x]?x:f[x]=find(f[x]);
}
void ddd(int x)
{
    f[x]=x;
    for(int i=h2[x]; i!=0; i=next[i])
    {
        a[x]++;
        if(f[to[i]]) a[find(to[i])]-=2;
    }
    for(int i=h1[x]; i!=0; i=next[i])
    {
        if(f[to[i]]==0)
        {
            ddd(to[i]);
            a[x]+=c[i+1>>1]=a[to[i]];
            f[to[i]]=x;
        }
    }
}
int main()
{
//  freopen("a.txt","r",stdin);
    int n,i,m,x,y;
    cnt=0;
    scanf("%d",&n);
    for(i=1; i<n; i++)
    {
        scanf("%d%d",&x,&y);
        add(h1,x,y);
        add(h1,y,x);
    }
    scanf("%d",&m);
    for(i=1; i<=m; i++)
    {
        scanf("%d%d",&x,&y);
        if(x==y) continue;
        add(h2,x,y);
        add(h2,y,x);
    }
    ddd(1);
    for(i=1; i<n; i++) printf("%d ",c[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40032278/article/details/81539251
今日推荐