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 }