题意:n个点连成的生成树(n个点,n-1条边,点与点之间都连通),如果某个点在两点之间的路径上,那这个点的繁荣度就+1,问你在所有点中,最大繁荣度是多少?就比如上面的图中的C点,在A-B,A-D,A-E,A-F,B-D,B-E,B-F的路径上,所以繁荣度为7。

思路:我们可以想一下,繁荣度是怎么来的?假设一个点的度是2,相当于以这个点为根,有两棵子树,那繁荣度就是这两棵子树上各取一个点两两组合,最后的结果就是两棵子树上的点的乘积。所以不难推出,若度大于2,那繁荣度就是所有子树上的点树两两相乘的和,例如上图的C点,度为3,且3个度包含的点的个数分别为1,1,3,繁荣度 = 1*1 + 1*3 + 1*3 = 7。

然而,这样的计算方式复杂度有点高,若度为n,光计算繁荣度就要O(n*n),更何况这只是一个点的繁荣度。所以,我们还可以简化一下计算方式:

计算出每一棵子树的点的个数,用每个子树的点的个数乘以除了这棵子树以及根节点以外剩余的点,,每棵子树都这样计算,并将结果相加,求出的和除以2,就是结果。

因为这样的计算方式和之前相比,相当于两两之间都乘了两次,子树1*所有子树的和(除自己) = 子树1*子树2* + 子树1*子树3 + .....  + 子树1*子树n, 子树2*所有子树的和(除自己) = 子树2*子树1 + 子树2*子树3 + ... + 子树2*子树n;这之中,子树1*子树2 ,又子树2*1子树,计算了两次,所以最终结果要除以2。

我们可以将整个图看成一棵以节点1为根的树,这样将会简化很多。除此之外,还可以使用链式前向星,记录下某个点与哪些点直接相连。这样,就可以节省寻找子树的时间

具体看代码:

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#define eps 1e-7
#define ll long long
#define inf 0x3f3f3f3f
#define pi 3.141592653589793238462643383279
using namespace std;
const int maxn = ;
int head[maxn],num,n;
ll ans,sum,size[maxn];
struct node{
int to,next;
}edge[maxn<<]; void add(int u,int v) //使用链式前向星计算每个点于那些点直接相连
{
edge[num].to = v;
edge[num].next = head[u];
head[u] = num++;
} void DFS(int u,int fa) //将整个图看成一棵树,u为当前节点,fa为父亲节点
{
ll res = ;
size[u] = ; //size[u]表示以u为根的树有多少个节点
for(int i=head[u]; i!=-; i=edge[i].next) //遍历所有子树
{
int to = edge[i].to;
if(to == fa) continue; //不计算父亲节点
DFS(to,u);
size[u] += size[to]; //以u为根的树的节点总数等于他所有子树的节点树之和
res += (n - size[to] - )*size[to]; //计算子树与其他剩余点的乘积
}
res += ( n - size[u] )*(size[u]-); //除所有子树外,u的根节点连成的树也是以u为根的一课子树
ans = max(ans,res/);
return;
} int main()
{
int t,cnt = ;
cin>>t;
while(t--)
{
ans = -;
num = ;
memset(head,-,sizeof(head));
memset(size,,sizeof(size));
scanf("%d",&n);
int start,end;
for(int i=; i<n-; ++i)
{
scanf("%d%d",&start,&end);
add(start,end); //start于end直接相连
add(end,start);//无向图,反过来也相连
}
DFS(,-);
printf("Case #%d: %lld\n",cnt++,ans);
}
return ;
}

最新文章

  1. OC KVC
  2. Activity生命周期(深入理解)
  3. C#方法封装与重构
  4. c++ 设计模式3 (重构技法 Template Method)
  5. 基于Jquery+Ajax+Json+高效分页
  6. Earth to developers: Grow up!
  7. java 格式化输出方法
  8. HTML5获取当前的经纬度坐标
  9. centos 安装 crontab 和 简单的使用教程
  10. java练习:质数,匿名内部类创建接口,抽象类派生子类,画圆,字节截取字符串,数字变钱币,五子棋,梭哈
  11. vue脚手架---vue-cli
  12. 查看mysql的版本号
  13. java中继承thread类的其他类的start()方法与run()方法
  14. python3内置函数大全(顺序排列)
  15. servlet的编码原理
  16. [置顶] linux c常用函数 (待完善)
  17. vmvare安装ubuntu后
  18. 数据库中varchar类型数据转换为numeric类型
  19. RxJava 1.x 笔记:变换型操作符
  20. 编译安装hadoop2.6.3

热门文章

  1. inline修饰虚函数的问题
  2. &#39;scalar deleting destructor&#39; 和 &#39;vector deleting destructor&#39;的区别
  3. Oracle中的一连接语句
  4. 积木城堡(dp)
  5. 0001_mysql 5.7.25安装初始化
  6. 20181205_C#窗体监听键盘事件
  7. 蓝桥杯历届试题-垒色子(DP+矩阵快速幂)
  8. JS中的this机制
  9. 接口自动化(六)--使用QQ邮箱发送邮件
  10. 清除MAC 可清除空间