POJ 3107 Godfather (树形dp)

题目链接

虽然题目不难,但是1A还是很爽, 只是刚开始理解错题意了,想了好久。 还有据说这个题用vector会超时,看了以后还是用邻接吧。

题意:

给一颗树,保证是一颗树,求去掉一个点以后的联通块里节点的数目的 最大值最小,求这样的点,并按照递增顺序输出。

分析:

d[father] = max(n-sum, d[son]);   sum代表这个节点以下的全部节点总数, 去掉一个节点的联通块的最大的节点数 等于 整个树里的节点数减去这个节点下的总数 和 子树的数目的

最大值。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <vector>
 8 #define LL __int64
 9 const int maxn = 50000+10;
10 const int INF = 1<<28;
11 using namespace std;
12 int head[maxn], vis[maxn], t, d[maxn];
13 int mi, n;
14 struct node
15 {
16     int u, v, ne;
17 }e[2*maxn];
18
19 void add(int u, int v)
20 {
21     e[t].u = u;
22     e[t].v = v;
23     e[t].ne = head[u];
24     head[u] = t++;
25 }
26 int dfs(int son, int fa)
27 {
28     int i, tmp, sum = 1, x;  //sum是以son为根节点的子树的全部的节点数
29     for(i = head[son]; i != -1; i = e[i].ne)
30     {
31         tmp = e[i].v;
32         if(tmp == fa) continue;  //避免回去。
33         x = dfs(tmp, son);
34         sum += x;
35         d[son] = max(d[son], x);
36     }
37     d[son] = max(d[son], n-sum);
38     if(d[son]<mi)
39     mi = d[son];
40     return sum;
41 }
42 int main()
43 {
44     int i, f;
45     while(~scanf("%d", &n))
46     {
47         memset(e, 0, sizeof(e));
48         memset(head, -1, sizeof(head));
49         memset(vis, 0, sizeof(vis));
50         memset(d, 0, sizeof(d));
51         t = 0;
52         mi = INF;
53
54         for(i = 1; i < n; i++)
55         {
56             int u, v;
57             scanf("%d%d", &u, &v);
58             add(u, v);
59             add(v, u);
60         }
61         dfs(1, -1);  //把给的树看成以1为根节点。
62
63         f = 0;
64         for(i = 1; i <= n; i++)
65         {
66            if(d[i]==mi)
67            {
68                if(f)
69                printf(" %d", i);
70                else
71                printf("%d", i);
72                f = 1;
73            }
74         }
75         printf("\n");
76     }
77     return 0;
78 }
时间: 2024-07-30 05:01:40

POJ 3107 Godfather (树形dp)的相关文章

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】

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 2342 (树形DP)

Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3863   Accepted: 2172 Description There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure

POJ 1849 Two (树形dp 树的直径 两种方法)

Two Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1232   Accepted: 619 Description The city consists of intersections and streets that connect them. Heavy snow covered the city so the mayor Milan gave to the winter-service a list of st

[POJ 1155] TELE (树形dp)

题目链接:http://poj.org/problem?id=1155 题目大意:电视台要广播电视节目,要经过中转机构,到观众.从电视台到中转商到观众是一个树形结构,经过一条边需要支付成本.现在给你每两个节点之间传播的成本,给你每个观众会付的钱,问你电视台在不亏本的情况下最多能给多少个观众看节目. 这是我的第一道树形dp..无耻的看了题解.. 设计状态:dp[u][i]代表以u为根的子树中有i个观众,能够得到的最大收入. 状态转移:dp[u][i] = max(dp[u][i],dp[u][i-

poj 1947 经典树形dp

经典树形dp:问在一棵树上最少删除多少条边可以分离出一个节点数为p的子树. 定义状态: dp[i][j]表示从i为根的子树上分离出一个节点数为j的子树的代价(最少需要删除的边数). 考虑i节点的每个儿子ii,ii可以选或者不选(切断),然后就转化成了背包问题. dp[u][j] = min( dp[u][j], dp[u][j - k] + dp[v][k] ); 1 #include <iostream> 2 #include <cstring> 3 #include <c

POJ Anniversary party 树形DP

/* 树形dp: 给一颗树,要求一组节点,节点之间没有父子关系,并且使得所有的节点的权值和最大 对于每一个节点,我们有两种状态 dp[i][0]表示不选择节点i,以节点i为根的子树所能形成的节点集所能获得的最大权值和 dp[i][1]表示选择节点i ,同上! 转移方程: dp[i][0]+=max(dp[i_son][1],dp[i_son][0])如果没选择的话,那么子树可选择可不选择 dp[i][1]+=dp[i_son][0] 选择了之后,子树只能不选择 最后输出max(dp[i][0],

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 2486-Apple Tree(树形DP)(难)

题意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值 思路:(思路转自http://blog.csdn.net/libin56842/article/details/10101807) 树形dp,比较经典的一个树形dp.首先很容易就可以想到用dp[root][k]表示以root为根的子树中最多走k时所能获得的最多苹果数,接下去我们很习惯地会想到将k步在root的所有子结点中分配,也就是进行一次背包,就可以得出此时状态的最优解了,但是这里还有一个问