UVALive 6436 The Busiest City (树形DP)

来源:互联网 发布:lg电视如何看网络电视 编辑:程序博客网 时间:2024/06/11 19:45

题意:给出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;}


1 0
原创粉丝点击