zoukankan      html  css  js  c++  java
  • 1060E Sergey and Subway(思维题,dfs)

    题意:给出一颗树,现在,给哪些距离为2的点对,加上一条边,问所有点对的距离和

    题解:如果没有加入新的边,距离和就会等于每条边的贡献,由于是树,我们用点来代表点上面的边,对于每条边,它的贡献将是(子树大小)*(n-子树大小)

    而这题加上了新边,我们依然这样算贡献,跨越旧边的次数,依然是(子树大小)*(n-子树大小),只不过都是两个两个的走,那么虽然跨越了这条边,但是它可能走的是新边,也就是他的贡献要除以2,对于那些真正跨越了旧边的点对,它其实不需要除2的,所以我们要把它加上,这些点对的数量是(奇数层点数*偶数层点数)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn=2e5+10;
    ll f[maxn],nex[2*maxn],to[2*maxn],cnt=0,vis[maxn],siz[maxn],num[3];
    void add(int a,int b)
    {
        cnt++;
        to[cnt]=b;
        nex[cnt]=f[a];
        f[a]=cnt;
    }
    int dfs(int x,int le)
    {
        siz[x]=1;
        vis[x]=1;
        num[le%2]++;
        for(int i=f[x];i;i=nex[i])
        {
            int v=to[i];
            if(vis[v]==0)
            {
                dfs(v,le+1);
                siz[x]+=siz[v];
            }
        }
        return siz[x];
    }
    int main()
    {
        int n;
        cin>>n;
        for(int i=1;i<=n-1;i++)
        {
            int a,b;
            scanf("%d %d",&a,&b);
            add(a,b);
            add(b,a);
        }
        dfs(1,1);
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=siz[i]*(n-siz[i]);
        }
        ans+=num[0]*num[1];
        cout<<ans/2<<endl;
    	return 0;
    }
    

    依然看不懂请参考:https://blog.csdn.net/qq_37555704/article/details/82948958?utm_source=blogxgwz2

  • 相关阅读:
    大数据面经
    mysql复习(2)
    java容器
    内存管理
    垃圾收集
    输入/输出流
    排序算法的稳定性及其汇总
    java传值与传引用
    linux复习6
    linux复习5
  • 原文地址:https://www.cnblogs.com/carcar/p/9812461.html
Copyright © 2011-2022 走看看