zoukankan      html  css  js  c++  java
  • Fools and Roads CodeForces

    Fools and Roads CodeForces - 191C

    题意:给出一棵n个节点的树,还有树上的k条简单路径(用路径的两个端点u和v表示),对于树上每一条边,求出其被多少条简单路径经过。

    方法:

    一开始想了很久..想要在倍增求lca的同时统计边经过的次数..然而发现这样子可以统计,但是统计的值拆不开...没有办法在合适时间内得到答案...并没有思路..

    想了很久发现,这其实就是个简单的树上差分,只要记录一下每个节点i到根节点路径上所有边都需要加的权值sum[i]就行了。

    对于每一组(u,v),题意操作转化为sum[u]++,sum[v]++,sum[lca(u,v)]-=2。

    最后用一遍dfs把sum拆开,这个"树上前缀和"是可以O(n)拆开的。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,LL> P;
    vector<LL> v[100100];
    vector<P> vv;
    LL T,n,ne,k;
    LL deep[100100],anc[100100][17],log2n,sum[100100],ans[100100];
    void dfs(LL x,LL fa)
    {
        LL i;
        anc[x][0]=fa;
        deep[x]=deep[fa]+1;
        for(i=1;i<=log2n;i++)
            anc[x][i]=anc[anc[x][i-1]][i-1];
        for(auto y:v[x])
            if(y!=fa)
                dfs(y,x);
    }
    LL lca(LL x,LL y)
    {
        LL t,i;
        if(deep[x]<deep[y])    swap(x,y);
        for(t=deep[x]-deep[y],i=0;t>0;t>>=1,i++)
            if(t&1)    x=anc[x][i];
        if(x==y)    return x;
        for(i=log2n;i>=0;i--)
            if(anc[x][i]!=anc[y][i])
            {
                x=anc[x][i];
                y=anc[y][i];
            }
        return anc[x][0];
    }
    void dfs2(LL x,LL fa)
    {
        for(auto y:v[x])
            if(y!=fa)
                dfs2(y,x);
        ans[x]+=sum[x];sum[fa]+=sum[x];
    }
    int main()
    {
        LL i,x,y;
        scanf("%lld",&n);log2n=log2(n);
        for(i=1;i<n;i++)
        {
            scanf("%lld%lld",&x,&y);
            v[x].push_back(y);
            v[y].push_back(x);
            vv.push_back(P(x,y));
        }
        dfs(1,0);
        scanf("%lld",&k);
        for(i=1;i<=k;i++)
        {
            scanf("%lld%lld",&x,&y);
            sum[x]++;sum[y]++;sum[lca(x,y)]-=2;
        }
        dfs2(1,0);
        for(auto k:vv)    printf("%lld ",ans[deep[k.first]>deep[k.second]?k.first:k.second]);
        return 0;
    }
  • 相关阅读:
    初始化ArrayList的两种方法
    MySQL最大连接数设置
    页面按钮的语义和可访问性
    H5+App开发框架汇总
    JS使用模板快速填充HTML控件数据
    Meta标签中的format-detection属性及含义
    java中@Qualifier("string")是什么用法
    MySQL 当记录不存在时insert,当记录存在时update
    美国40岁以上的程序员在干啥
    老程序员都去哪了?
  • 原文地址:https://www.cnblogs.com/hehe54321/p/cf-191c.html
Copyright © 2011-2022 走看看