UVALive - 6436

题目链接:https://vjudge.net/contest/241341#problem/C

Tree Land Kingdom is a prosperous and lively kingdom. It has N cities which are connected to each other by roads such that there is exactly one path to go from one city to any other city. Each road in the kingdom connects exactly two different cities. Every day a lot of merchants travel from one city to other cities in the kingdom making this kingdom famous for its commerce. The king of this kingdom wonders, which city is the busiest one in his entire kingdom. The busyness of a city is defined as the number of merchants who visits this city on each day. A merchant is considered as visiting c city if and only if city c lies on the path when the merchant travels from city a to city b. Unfortunately, we need a lot of resources and time to answer the king’s question. Therefore, the ministers come up with an idea to approximate the answer so they can provide the king with an “early” answer while they are working on the actual answer. To approximate the answer, the ministers modify the definition of a city’s busyness a bit. The busyness of a city a is now defined as the number of different pair of cities a−b such that c lies in a simple path from a to b (note that c is neither a nor c). A path is considered simple if and only if it does not visit any city more than once. Consider the example as shown in Figure 1 below.
In this example, the busyness of city A, B, E and F are 0 because there is no pair of cities which path visits those nodes. The busyness of city C is 7 (the pairs are: A-B, A-D, A-E, A-F, B-D, B-E, B-F) and the busyness of city D is also 7 (the pairs are: A-E, A-F, B-E, B-F, C-E, C-F, E-F). Therefore, the highest busyness in this example is 7, which occurs in city C and D. Given the kingdom’s road structure, your task is to determine the highest busyness among all cities in the kingdom.
Input The first line of input contains an integer T (T ≤ 50) denoting the number of cases. Each case begins with an integer N (3 ≤ N ≤ 20,000) denoting the number of cities in the kingdom. The cities are numbered from 1 to N. The following N −1 lines each contains two integers a and b (1 ≤ a,b ≤ N) denoting a road which connects city a and city b.
Output
For each case, output ‘Case #X: Y ’, where X is the case number starts from 1 and Y is the highest busyness among all cities in the kingdom for that case.
Notes: • Explanation for 1st sample case This sample case corresponds to Figure 1 in the problem statement. • Explanation for 2nd sample case The busiest city is city 2 with busyness of 1 (the pair is: 1-3). • Explanation for 3rd sample case The busiest city is city 2 with busyness of 3 (the pairs are: 1-3, 1-4, 3-4).
Sample Input
4 6 1 3 2 3 3 4 4 5 4 6 3 1 2 2 3 4 1 2 2 3 2 4 7 2 5 1 2 7 4 3 7 2 3 7 6
Sample Output
Case #1: 7 Case #2: 1 Case #3: 3 Case #4: 9

题目大意:输入t,代表t组样例,输入n,接下来有n-1条边,问你一个点被经过的最多次数是多少,如果刚好到该点不算经过,所以叶子节点都算经过0次

个人思路:这道题首先要推出来经过的次数由哪几部分组成:可以把该点看作根,那么就是求它的子树的问题了,该点的次数有两部分组成:

第一部分:该点有n个子树,每个子树的节点数乘以其它子树的总节点数

第二部分:一个子树上的节点之间也有路,所以也要相乘(我这里的算法是多算了一倍,所以要除以2)

看代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<math.h>
#include<algorithm>
#include<set>
#include<queue>
#include<map>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=2e4+10;
const int maxk=100+10;
const int maxx=1e4+10;
const ll maxe=1000+10;
#define INF 0x3f3f3f3f3f3f
vector<int>p[maxn];
int Po[maxn];
int ans=0,n;
void dfs(int now,int pre)
{
    for(int i=0;i<p[now].size();i++)
    {
        int v=p[now][i];
        if(v!=pre)
        {
            dfs(v,now);
            Po[now]+=Po[v];//该点除了自己和pre有多少个节点
        }
    }
    int sum1=0,sum2=0;
    sum1=Po[now]*(n-1-Po[now]);//自己集合的节点数*不属于自己集合的节点数(不包括本身)
    for(int i=0;i<p[now].size();i++)
    {
        int v=p[now][i];
        if(v!=pre)
        {
           // sum2+=Po[v]*(p[now].size()-Po[v]);
           sum2+=Po[v]*(Po[now]-Po[v]);//自己集合的节点之间也会有路径
        }
    }
    sum2=sum2/2;//相当于乘了两遍,所以除以2
    if(ans<sum1+sum2)
        ans=sum1+sum2;
    Po[now]++;//加上自己
}
int main()
{
    ios::sync_with_stdio(false);
    int t;
    int sum=1;
    cin>>t;
    while(t--)
    {
        for(int i=0;i<maxn;i++)
            p[i].clear();//每次都要清空
        ans=0;
        memset(Po,0,sizeof(Po));
        int a,b;
        cin>>n;
        for(int i=1;i<n;i++)
        {
            cin>>a>>b;
            p[a].push_back(b);
            p[b].push_back(a);
        }
        dfs(1,0);//从第一个节点开始遍历(其实任意一个节点都可以)
        printf("Case #%d: %d\n",sum++,ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caijiaming/p/9384707.html