POJ 3107

树的重心,EASY题。

树的重心定义为:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重

心后,生成的多棵树尽可能平衡.  实际上树的重心在树的点分治中有重要的作用, 可以避免N^2的极端复杂度(从退化链的一端出发),保证

NlogN的复杂度, 利用树型dp可以很好地求树的重心.

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cctype>
 5 #include <algorithm>
 6 #define LL unsigned __int64
 7 using namespace std;
 8
 9 const int N=  50100;
10
11 struct Edge{
12     int u,v;
13     int next;
14 }edge[N*2];
15 int head[N],tot,maxt;
16 int dp[N],n,ans[N],anc;
17
18 void addedge(int u,int v){
19     edge[tot].u=u;
20     edge[tot].v=v;
21     edge[tot].next=head[u];
22     head[u]=tot++;
23 }
24
25 void dfs(int u,int f){
26     dp[u]=1;
27     int tmp=-1;
28     int v;
29     for(int e=head[u];e!=-1;e=edge[e].next){
30         v=edge[e].v;
31         if(v!=f){
32             dfs(v,u);
33             dp[u]+=dp[v];
34             tmp=max(tmp,dp[v]);
35         }
36     }
37     tmp=max(tmp,n-dp[u]);
38     if(tmp<maxt){
39         anc=0;
40         maxt=tmp;
41         ans[anc++]=u;
42     }
43     else if(tmp==maxt)
44     ans[anc++]=u;
45 }
46
47 int main(){
48     int u,v;
49     while(scanf("%d",&n)!=EOF){
50         for(int i=1;i<=n;i++){
51             head[i]=-1; dp[i]=0;
52         }
53         tot=0; anc=0; maxt=N*10;
54         for(int i=1;i<n;i++){
55             scanf("%d%d",&u,&v);
56             addedge(u,v);
57             addedge(v,u);
58         }
59         dfs(1,-1);
60         sort(ans,ans+anc);
61         printf("%d",ans[0]);
62         for(int i=1;i<anc;i++)
63         printf(" %d",ans[i]);
64         puts("");
65     }
66     return 0;
67 }

时间: 2024-10-12 00:04:53

POJ 3107的相关文章

POJ 3107 Godfather (树的重心)

题目地址:POJ 3107 还是裸的树的重心,只不过这个要求将所有的重心都输出.很简单. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include &

poj 3107 Godfather 求树的重心【树形dp】

poj 3107 Godfather 和poj 1655差不多,那道会了这个也就差不多了. 题意:从小到大输出树的重心. 题会卡stl,要用邻接表存树..... 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn = 50006; 7 const int INF = 1

poj 3107 树重心

http://acm.hust.edu.cn/vjudge/problem/18069 和poj 1655差不多:http://www.cnblogs.com/qlky/p/5780933.html 区别就是要记录所有的重心 #include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath

POJ 3107 Godfather

Godfather 时限:2000ms Description Last years Chicago was full of gangster fights and strange murders. The chief of the police got really tired of all these crimes, and decided to arrest the mafia leaders. Unfortunately, the structure of Chicago mafia i

poj 3107 Godfather (树形dp)

Godfather Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5064   Accepted: 1769 Description Last years Chicago was full of gangster fights and strange murders. The chief of the police got really tired of all these crimes, and decided to

POJ 3107 Godfather (树形dp)

题目链接 虽然题目不难,但是1A还是很爽, 只是刚开始理解错题意了,想了好久. 还有据说这个题用vector会超时,看了以后还是用邻接吧. 题意: 给一颗树,保证是一颗树,求去掉一个点以后的联通块里节点的数目的 最大值最小,求这样的点,并按照递增顺序输出. 分析: d[father] = max(n-sum, d[son]);   sum代表这个节点以下的全部节点总数, 去掉一个节点的联通块的最大的节点数 等于 整个树里的节点数减去这个节点下的总数 和 子树的数目的 最大值. 1 #includ

poj 1655 and 3107 and 2378 树形dp(树的重心问题)

简单的树形dp,顺便学习了树的重心的概念,即以该点为根的树的最大子树的结点数最少. poj 1655: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 20001; 7 int head[N]; 8 int balance[N]; 9 int child[N]; 10 int n, e; 11 12 struct

树形 DP 总结

本文转自:http://blog.csdn.net/angon823/article/details/52334548 介绍 1.什么是树型动态规划 顾名思义,树型动态规划就是在"树"的数据结构上的动态规划,平时作的动态规划都是线性的或者是建立在图上的,线性的动态规划有二种方向既向前和向后,相应的线性的动态规划有二种方法既顺推与逆推,而树型动态规划是建立在树上的,所以也相应的有二个方向: 1.叶->根:在回溯的时候从叶子节点往上更新信息 2.根 - >叶:往往是在从叶往根d

DP Intro - Tree DP Examples

因为上次比赛sb地把一道树形dp当费用流做了,受了点刺激,用一天时间稍微搞一下树形DP,今后再好好搞一下) 基于背包原理的树形DP poj 1947 Rebuilding Roads 题意:给你一棵树,让你求最少剪掉多少条边可以剪出一棵点数为m的子树. 解法:dp[i][j]表示i节点得到j个节点的子树至少要剪多少边,对于每个节点a和它的孩子b,如果剪掉b,则dp(s)[a][j]=dp(s-1)[a][j], 如果保留<a,b>dp(s)[a][j]=min{dp(s-1)[a][j - k