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

  • 相关阅读:
    .NET Core 使用Dapper 操作MySQL
    .NET Core HtmlAgilityPack HTML解析利器
    ASP.NET Core 开发-缓存(Caching)
    .NET Core 调用WCF 服务
    ASP.NET Core 开发-Logging 使用NLog 写日志文件
    Qt动态生成界面并通过拉姆达获取其返回值
    Qt启动C++线程并在线程中修改界面
    Vector求最大值最小值
    C/C++取消结构体字节对齐
    Matlab定时器
  • 原文地址:https://www.cnblogs.com/carcar/p/9812461.html
Copyright © 2011-2022 走看看