UVALive 6436 The Busiest City (树形DP)

题意:给出n个顶点,n-1条边,对于每一个顶点来说每有一条路径经过,繁荣度+1,求最大繁荣度。


思路:从任意一个节点开始dfs,找到当前根有多少子集,和不在当前根子集中的节点做乘法,就是当前根的子集和外

面各个点的路径数,就是经过当前根的一部分次数,设为sum1。然后再在根内,假设这个根是A,找到A的每一个子

和A内其他子集的乘积,这是根内的路径个数,也是经过A的另一部分次数sum2,但是每一个子集都和其他子集做

法,相当于乘了两遍,最后再除以2,和原来的次数sum1相加就是总的经过A的路径数目。




#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 2e4+5;
vector<int> g[maxn];
int n, ans, cnt[maxn];

void dfs(int cur, int pre)
{
    for(int i = 0; i < g[cur].size(); i++)
    {
        int v = g[cur][i];
        if(v != pre)
        {
            dfs(v, cur);
            cnt[cur] += cnt[v];
        }
    }
    int sum1 = cnt[cur]*(n-1-cnt[cur]);
    int sum2 = 0;
    for(int i = 0; i < g[cur].size(); i++)
    {
        int v = g[cur][i];
        if(v != pre)
            sum2 += cnt[v]*(cnt[cur]-cnt[v]);
    }
    int sum = sum1+sum2/2;
    if(sum > ans) ans = sum;
    cnt[cur]++;
}

int main(void)
{
    int t, ca = 1;
    cin >> t;
    while(t--)
    {

        for(int i = 0; i < maxn; i++)
            g[i].clear();
        scanf("%d", &n);
        for(int i = 1; i < n; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        ans = 0;
        memset(cnt, 0, sizeof(cnt));
        dfs(1, 0);
        printf("Case #%d: %d\n", ca++, ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值