标签:style blog http color os io for art
poj 1655:http://poj.org/problem?id=1655
题意: 给无根树, 找出以一节点为根, 使节点最多的树,节点最少。
题解:一道树形dp,先dfs 标记 所有节点的子树的节点数。 再dfs 找出以某节点为根的最大子树,节点最少。 复杂度(n)
/***Good Luck***/ #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <stack> #include <map> #include <queue> #include <vector> #include <set> #include <functional> #include <cmath> #define Zero(a) memset(a, 0, sizeof(a)) #define Neg(a) memset(a, -1, sizeof(a)) #define All(a) a.begin(), a.end() #define PB push_back #define inf 0x7fffffff #define inf2 0x7fffffffffffffff #define ll long long using namespace std; const int maxn = 100000; int n, k, e, head[maxn]; int mx[maxn], sum[maxn], ansn, ansb; struct Node { int next, v; }node[maxn]; void input(int u, int v) { node[e].next = head[u]; node[e].v = v; head[u] = e++; } int dfssize(int b, int fa) { sum[b] = 1; mx[b] = 0; int tmpmx; for (int i = head[b]; ~i; i = node[i].next) { int v = node[i].v; if (fa != v) { tmpmx = dfssize(v, b); sum[b] +=tmpmx; if (tmpmx > mx[b]) mx[b] = tmpmx; } } return sum[b]; } void solve(int b, int fa) { int tmpmx; tmpmx = max(mx[b], n - sum[b]); if (tmpmx <= ansb) { if (tmpmx < ansb) { ansn = b; ansb = tmpmx; } else if (b < ansn) { ansn = b; ansb = tmpmx; } } for (int i = head[b]; ~i; i = node[i].next) { int v = node[i].v; if (fa != v) { solve(v, b); } } } int main() { int u, v; int T; scanf("%d", &T); while (T-- ) { scanf("%d", &n); e = 0; Neg(head); for (int i = 0; i < n - 1; ++i) { scanf("%d%d", &u, &v); input(u, v); input(v, u); } dfssize(1, 0); ansb = inf; solve(1, 0); printf("%d %d\n", ansn, ansb); } return 0; }
poj 1741:http://poj.org/problem?id=1741
题意:给一值k,在带权无向图G中, 找出两节点相距不大于k的数。
qzc论文的第一题(膜拜q神 orz),根据论文写的 代码, 先写了一题树形dp(1655),再开始写这的,搞了一晚上具体的还是看论文吧。
找根(n), 计算(logn), 一共执行 logn次 总复杂度(n*logn*logn)
1 /***Good Luck***/ 2 #define _CRT_SECURE_NO_WARNINGS 3 #include <iostream> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #include <stack> 10 #include <map> 11 #include <queue> 12 #include <vector> 13 #include <set> 14 #include <functional> 15 #include <cmath> 16 17 #define Zero(a) memset(a, 0, sizeof(a)) 18 #define Neg(a) memset(a, -1, sizeof(a)) 19 #define All(a) a.begin(), a.end() 20 #define PB push_back 21 #define inf 0x3f3f3f3f 22 #define inf2 0x7fffffffffffffff 23 #define ll long long 24 using namespace std; 25 const int maxn = 20000; 26 int head[maxn], n, k, e; 27 int ans, sum[maxn], mx[maxn]; 28 bool vis[maxn]; 29 int dis[maxn], a[maxn], an; 30 struct Node { 31 int w; 32 int v, next; 33 }edge[maxn]; 34 35 void init() { 36 e = 0; 37 ans = 0; 38 Neg(head); 39 Zero(vis); 40 } 41 42 void add(int u, int v, int w) { //邻接表储存 43 edge[e].v = v; 44 edge[e].w = w; 45 edge[e].next = head[u]; 46 head[u] = e++; 47 } 48 49 int dfssize(int u, int fa) { //标记子树的节点数 50 sum[u] = 1; 51 mx[u] = 0; 52 int tmpmx; 53 for (int i = head[u]; ~i; i = edge[i].next) { 54 int v = edge[i].v; 55 if (v != fa && !vis[v]) { 56 tmpmx = dfssize(v, u); 57 sum[u] += tmpmx; 58 if (tmpmx > mx[u]) mx[u] = tmpmx; 59 } 60 } 61 return sum[u]; 62 } 63 64 int ansn, mxshu; 65 void find_root(int u, int fa, int nn) { // 找出符合条件的根。 66 int tmpmx = max(mx[u], nn - sum[u]); 67 if (tmpmx < mxshu) { 68 ansn = u; 69 mxshu = tmpmx; 70 } 71 for (int i = head[u]; ~i; i = edge[i].next) { 72 int v = edge[i].v; 73 if (v != fa && !vis[v]) { 74 find_root(v, u, nn); 75 } 76 } 77 } 78 79 void dfsdis(int u, int fa) { 80 a[an++] = dis[u]; 81 for (int i = head[u]; ~i; i = edge[i].next) { 82 int v = edge[i].v; 83 if (fa != v && !vis[v]) { 84 dis[v] = dis[u] + edge[i].w; 85 dfsdis(v, u); 86 } 87 } 88 } 89 90 int cal(int u, int fa, int beg) { // 这个方法太神奇了 复杂度只有 (logn) 91 an = 0; 92 int ret = 0; 93 dis[u] = beg; 94 dfsdis(u, fa); 95 sort(a, a + an); 96 int l = 0, r = an - 1; 97 while (l < r) { 98 if (a[r] + a[l] <= k ) 99 ret += r - l++; 100 else 101 r--; 102 } 103 return ret; 104 } 105 106 void solve(int u) { 107 dfssize(u, 0); 108 mxshu = inf; 109 find_root(u, 0, sum[u]); 110 vis[ansn] = true; 111 ans += cal(ansn, 0, 0); 112 for (int i = head[ansn]; ~i; i = edge[i].next) { 113 int v = edge[i].v; 114 if (!vis[v]) { 115 ans -= cal(v, ansn, edge[i].w); 116 solve(v); 117 } 118 } 119 } 120 int main() { 121 //freopen("data.out", "w", stdout); 122 //freopen("data.in", "r", stdin); 123 int u, v, w; 124 while (scanf("%d%d", &n, &k), n&&k) { 125 init(); 126 for (int i = 0; i < n - 1; ++i) { 127 scanf("%d%d%d", &u, &v, &w); 128 add(u, v, w); 129 add(v, u, w); 130 } 131 solve(1); 132 printf("%d\n", ans); 133 } 134 return 0; 135 }
树的点分治 (poj 1741, 1655(树形dp)),布布扣,bubuko.com
标签:style blog http color os io for art
原文地址:http://www.cnblogs.com/yeahpeng/p/3898994.html