zoukankan      html  css  js  c++  java
  • [数学] JZOJ P3636 分叉

    Description

    给出一棵N 个点的树,点的编号是1, 2,。。。,N。
    对于3 个点{a,b,c},如果不存在一条简单路径同时经过a,b,c,那么{a,b,c}是一个分叉。
    统计不同分叉的数量。
    树 无环,连通的无向图
    简单路径 不重复经过同一个点的路径

    Input

    第1 行,1 个整数N。接下来(N -1) 行,每行2 个整数Ai,Bi,表示点Ai 和点Bi 间有一条边。

    Output

    1 个整数,表示所求的值。

    Sample Input

    5

    1 2

    1 3

    1 4

    1 5

    Sample Output

    4

    Data Constraint

    • 对于30% 的数据,N <= 100;

    • 对于50% 的数据,N <= 1000;

    • 对于100% 的数据,1 <= N <= 10^5。

    题解

    我们可以统计出每个节点的子树大小
    然后,可以换一种方法想:我们求出所有可能的C(n,3)-可以用简单路径连成的点=不可以的点
    题目说没有重复的情况出现,那么对于一个节点作“中转站”的情况下,是存在有
    这里写图片描述
    然后我们每次换根,求下一个节点可以求出的和

    代码

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int zs[200010],father[200010],last[400010],head[200010],next[400010],n,tot,a[200010],b[200010];
    long long ans,num;
    void insert(int x,int y)
    {
        last[++tot]=y;
        next[tot]=head[x];
        head[x]=tot;
    }
    void find (int x)
    {
        zs[x]=1;
        for (int i=head[x];i;i=next[i])
            if (last[i]!=father[x])
            {
                father[last[i]]=x;
                find(last[i]);
                zs[x]+=zs[last[i]]; 
            }
    }
    void dfs (int x)
    {
        num=0;
        for(int i=head[x];i;i=next[i])
        {
            ans+=(long long)num*zs[last[i]];
            num+=zs[last[i]];
        }
        a[x]=zs[x];
        for (int i=head[x];i;i=next[i])
            if (last[i]!=father[x])
            {
                zs[x]=a[x];
                b[x]=zs[last[i]];
                zs[x]-=zs[last[i]];
                zs[last[i]]+=zs[x];
                dfs(last[i]);
                zs[last[i]]=b[x];
            }
    }
    int main()
    {
        freopen("fork.in","r",stdin);
        freopen("fork.out","w",stdout);
        scanf("%d",&n);
        int x,y;
        for (int i=1;i<=n-1;i++)
        {
            scanf("%d%d",&x,&y);
            insert(x,y);
            insert(y,x);
        }
        find(1);
        dfs(1);
        long long sum=(long long)n*(n-1)*(n-2)/6;
        printf("%lld",sum-ans);
        return 0;
    }
  • 相关阅读:
    .NET中非对称加密RSA算法的密钥保存
    WGS84经纬度坐标到北京54高斯投影坐标的转换[转]
    [APPS] HTC Footprints & HTC Locations for MikG 2.x Read more:
    firefox+ssh无法看youtube视频的解决方案
    【转】sdemon命令实践
    How to share a custom ArcMap command (DLL)
    【转】sdemon命令实践
    红旗桌面版本最新运用法子和结果解答100例8
    红旗Linux桌面4.1文本安装过程图解(二)
    Ubuntu把在效能器范畴起更重要的脚色
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412232.html
Copyright © 2011-2022 走看看