树的重心求法+POJ 1655
来源:互联网 发布:淘宝nike专卖店 编辑:程序博客网 时间:2024/05/17 08:14
树的重心,也叫树的质心,可以这样定义,对于一棵n个结点的无根树,找到一个点,使得把树变成以该点为根的有根树时,最大子树的结点数最小,换句话说,删除这个点之后的最大连通块(一定是树结构)的结点数最小
———刘汝佳
本文是对刘汝佳的树的重心讲解的衍生和解释
求法是和树的最大集问题类似的,先选一个点作为根,然后把无根树转化为有根树,设dp[i]表示以i为根的结点个数,不难发现
(
显然可以一遍DFS进行求解,那么删除结点i后,最大的连通块有多少个节点呢,结点i的子树中最大的是max(dp[j]),那么i的上方子树为n-max(dp[i]),其原因是我们可以想象一个点,其上的父亲以及上面的所有点(其实是除去i及i的所有子点的点),将其想象成一个i的子树,这样一来,改点删去之后最大的联通块的size就是max(max(dp[j]),n-dp[i]);
所以可以在dp的过程中找出树的重心
代码如下
#include<cstdio>#include<iostream>#include<cstring>#include<map>#include<vector>#include<queue>#define MAXN 100000+10using namespace std;int n,m;struct Line{ int from,to,nxt;}line[MAXN];int head[MAXN],tail,son[MAXN];int ans=0x7fffffff,loc=0x7fffffff;bool vis[MAXN];void add_line(int from,int to){ tail++; line[tail].from=from; line[tail].to=to; line[tail].nxt=head[from]; head[from]=tail;} void dpp(int u){ son[u]=0; vis[u]=true; int temp=-0x3f3f3f; for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(!vis[v]){ dpp(v); son[u]+=son[v]; temp=max(temp,son[v]); } } son[u]++; temp=max(temp,n-son[u]); if(temp<ans||temp==ans&&u<loc){ ans=temp; loc=u; }}int main(){ //freopen(".txt","r",stdin); //freopen(".out","w",stdout); scanf("%d%d",&n,&m); for(register int i=1;i<=m;i++){ int from,to; scanf("%d%d",&from,&to); add_line(from,to); add_line(to,from); } dpp(1); printf("%d %d\n",ans,loc); return 0;}
上述是思路,然后写了一道POJ的裸题 POJ1655
1A代码:
#include<cstdio>#include<iostream>#include<cstring>#include<map>#include<vector>#include<queue>#define MAXN 100000+10using namespace std;int n,m;struct Line{ int from,to,nxt;}line[MAXN];int head[MAXN],tail,son[MAXN],T;int ans=0x7fffffff,loc=0x7fffffff;bool vis[MAXN];void add_line(int from,int to){ tail++; line[tail].from=from; line[tail].to=to; line[tail].nxt=head[from]; head[from]=tail;} void dpp(int u){ son[u]=0; vis[u]=true; int temp=-0x3f3f3f; for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(!vis[v]){ dpp(v); son[u]+=son[v]; temp=max(temp,son[v]); } } son[u]++; temp=max(temp,n-son[u]); if(temp<ans||temp==ans&&u<loc){ ans=temp; loc=u; }}int main(){ //freopen(".txt","r",stdin); //freopen(".out","w",stdout); scanf("%d",&T); while(T--){ scanf("%d",&n); loc=ans=0x7fffffff; memset(head,0,sizeof(head)),tail=0; memset(vis,false,sizeof(vis)); for(register int i=1;i<=n-1;i++){ int from,to; scanf("%d%d",&from,&to); add_line(from,to); add_line(to,from); } dpp(1); printf("%d %d\n",loc,ans); } return 0;}/*231 2 2 342 12 33 41 3*/
阅读全文
0 0
- 树的重心求法+POJ 1655
- poj 1655 Balancing Act 求树的重心(详解树重心求法)
- 树的重心求法POJ3107
- POJ 1655 树的重心
- poj 1655 树的重心
- poj 1655 树的重心
- poj-1655 树的重心
- 树的重心 poj-1655
- 树的重心 poj
- POJ 1655 Balancing Act【树的重心】
- POJ 1655(求树的重心)
- poj 1655 Balancing Act 【树的重心】
- POJ-1655 Balancing Act 树的重心
- 【POJ】1655 Balancing Act 树的重心
- 【树的重心】 POJ 1655 Balancing Act
- poj 1655 求树的重心
- POJ 1655 Balancing Act 树的重心
- 【POJ 1655】Balancing Act 【树的重心】
- C/C++的sizeof('a')和sizeof(char)
- hadoop 2.0中配置文件详解
- C++实现读取特定路径下文件夹及文件名的方法
- Fiddler抓包使用教程-基本功能介绍
- 人生之清单(list of life)
- 树的重心求法+POJ 1655
- BZOJ4590: [Shoi2015]自动刷题机
- PCM双声道分离为单声道
- android中的自定义封装易用的Dialog
- Thinking in Java整理笔记
- Python学习之旅-15
- Windows上搭建Tomcat本地服务器教程--自我积累
- 无协作,不原型!
- 如何用快启动pe修复win10系统引导?