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 Edge
13 {
14     int v, next;
15 } edge[N * 2];
16
17 void addEdge( int u, int v )
18 {
19     edge[e].v = v;
20     edge[e].next = head[u];
21     head[u] = e++;
22 }
23
24 void dfs( int u, int fa )
25 {
26     balance[u] = 0;
27     child[u] = 1;
28     for ( int i = head[u]; i != -1; i = edge[i].next )
29     {
30         int v = edge[i].v;
31         if ( v != fa )
32         {
33             dfs( v, u );
34             balance[u] = max( balance[u], child[v] );
35             child[u] += child[v];
36         }
37     }
38     balance[u] = max( balance[u], n - child[u] );
39 }
40
41 int main ()
42 {
43     int t;
44     scanf("%d", &t);
45     while ( t-- )
46     {
47         scanf("%d", &n);
48         e = 0;
49         memset( head, -1, sizeof(head) );
50         for ( int i = 1; i < n; i++ )
51         {
52             int u, v;
53             scanf("%d%d", &u, &v);
54             addEdge( u, v );
55             addEdge( v, u );
56         }
57         dfs( 1, -1 );
58         int ans = 1;
59         for ( int i = 2; i <= n; i++ )
60         {
61             if ( balance[i] < balance[ans] )
62             {
63                 ans = i;
64             }
65         }
66         printf("%d %d\n", ans, balance[ans]);
67     }
68     return 0;
69 }

poj 3107:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5
 6 const int N = 50001;
 7 int head[N];
 8 int balance[N];
 9 int child[N];
10 int n, e;
11
12 struct Edge
13 {
14     int v, next;
15 } edge[N * 2];
16
17 void addEdge( int u, int v )
18 {
19     edge[e].v = v;
20     edge[e].next = head[u];
21     head[u] = e++;
22 }
23
24 void dfs( int u, int fa )
25 {
26     balance[u] = 0;
27     child[u] = 1;
28     for ( int i = head[u]; i != -1; i = edge[i].next )
29     {
30         int v = edge[i].v;
31         if ( v != fa )
32         {
33             dfs( v, u );
34             balance[u] = max( balance[u], child[v] );
35             child[u] += child[v];
36         }
37     }
38     balance[u] = max( balance[u], n - child[u] );
39 }
40
41 int main ()
42 {
43     while ( scanf("%d", &n) != EOF )
44     {
45         e = 0;
46         memset( head, -1, sizeof(head) );
47         for ( int i = 1; i < n; i++ )
48         {
49             int u, v;
50             scanf("%d%d", &u, &v);
51             addEdge( u, v );
52             addEdge( v, u );
53         }
54         dfs( 1, -1 );
55         int minn = 1;
56         for ( int i = 2; i <= n; i++ )
57         {
58             if ( balance[i] < balance[minn] )
59             {
60                 minn = i;
61             }
62         }
63         printf("%d", minn);
64         for ( int i = minn + 1; i <= n; i++ )
65         {
66             if ( balance[i] == balance[minn] )
67             {
68                 printf(" %d", i);
69             }
70         }
71         puts("");
72     }
73     return 0;
74 }

poj 2378:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5
 6 const int N = 10001;
 7 int head[N];
 8 int balance[N];
 9 int child[N];
10 int n, e;
11
12 struct Edge
13 {
14     int v, next;
15 } edge[N * 2];
16
17 void addEdge( int u, int v )
18 {
19     edge[e].v = v;
20     edge[e].next = head[u];
21     head[u] = e++;
22 }
23
24 void dfs( int u, int fa )
25 {
26     balance[u] = 0;
27     child[u] = 1;
28     for ( int i = head[u]; i != -1; i = edge[i].next )
29     {
30         int v = edge[i].v;
31         if ( v != fa )
32         {
33             dfs( v, u );
34             balance[u] = max( balance[u], child[v] );
35             child[u] += child[v];
36         }
37     }
38     balance[u] = max( balance[u], n - child[u] );
39 }
40
41 int main ()
42 {
43     while ( scanf("%d", &n) != EOF )
44     {
45         e = 0;
46         memset( head, -1, sizeof(head) );
47         for ( int i = 1; i < n; i++ )
48         {
49             int u, v;
50             scanf("%d%d", &u, &v);
51             addEdge( u, v );
52             addEdge( v, u );
53         }
54         dfs( 1, -1 );
55         for ( int i = 1; i <= n; i++ )
56         {
57             if ( balance[i] <= n / 2 )
58             {
59                 printf("%d\n", i);
60             }
61         }
62     }
63     return 0;
64 }
时间: 2024-12-15 09:34:47

poj 1655 and 3107 and 2378 树形dp(树的重心问题)的相关文章

hdu-4118 Holiday&#39;s Accommodation(树形dp+树的重心)

题目链接: Holiday's Accommodation Time Limit: 8000/4000 MS (Java/Others)     Memory Limit: 200000/200000 K (Java/Others) Problem Description Nowadays, people have many ways to save money on accommodation when they are on vacation.One of these ways is exc

POJ 1655 Balancing Act (树形dp 树的重心)

Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10596   Accepted: 4398 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or m

POJ3107Godfather[树形DP 树的重心]

Godfather Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6121   Accepted: 2164 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

cqyz oj | 树的分治 | 树形DP | 树的重心

Description 给定一棵N个节点的带权树,定义dist(u,v)为u,v两点间的最短路径长度,路径的长度义为路径上所有边的权和.再给定一个K,如果对于不同的两个结点a,b,如果满足dist(a,b)<=K,则称(a,b)为合法点对. 你的任务是求合法点对个数. Input 第一行包含两个个整数N和K,接下来的N-1行,每行包含三个整数:u,v,len,表示树边(u,v)的长度len. Output 一个整数,表示合法点对的数目. Sample Input 1 5 4 1 2 3 1 3

树形DP+树状数组 HDU 5877 Weak Pair

1 //树形DP+树状数组 HDU 5877 Weak Pair 2 // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 3 // 这道题要离散化 4 5 #include <bits/stdc++.h> 6 using namespace std; 7 #define LL long long 8 typedef pair<int,int> pii; 9 const double inf = 12345678901234

POJ 1655 BalanceAct 3107 Godfather (树的重心)(树形DP)

参考网址:http://blog.csdn.net/acdreamers/article/details/16905653 树的重心的定义: 树的重心也叫树的质心.找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡. 通常利用树形DP找重心: BalanceAct: http://poj.org/problem?id=1655 题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最

POJ 2342 &amp;&amp;HDU 1520 Anniversary party 树形DP 水题

一个公司的职员是分级制度的,所有员工刚好是一个树形结构,现在公司要举办一个聚会,邀请部分职员来参加. 要求: 1.为了聚会有趣,若邀请了一个职员,则该职员的直接上级(即父节点)和直接下级(即儿子节点)都不能被邀请 2.每一个员工都有一个兴奋值,在满足1的条件下,要使得邀请来的员工的兴奋值最高 输出最高的兴奋值. 简单的树形DP dp[i][1]:表示以i为根的子树,邀请节点i的最大兴奋值 dp[i][0]:表示以i为根的子树,不邀请节点i的最大兴奋值 先根据入度找出整棵树的根节点, 然后一次DF

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 3398 / UVA 1218 Perfect Service 树形DP

树形DP Perfect Service Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1378   Accepted: 668 Description A network is composed of N computers connected by N ? 1 communication links such that any two computers can be communicated via a uniqu