Tree
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 12276 | Accepted: 3886 |
Description
Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input
The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
Sample Input
5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0
Sample Output
8
题意:求树上距离小于等于k的点对数。。
我是用 点的分治做的,,据说还可以用启发式合并做,,附上链接http://blog.csdn.net/asdfgh0308/article/details/39845489。。挖个坑。
定义树的重心 s 为 删除s点后的 最大子树的点数 小于n/2。 那么对于任意满足条件的点对 有两种情况,,
其路径 1要么经过s 2要么不经过s。。
对于1 我们只需要 求出 以s为根的子树的点到s的距离即可。。
对于2 可以递归处理 分解为 多个1。。然后就可以求出来了。。
复杂度为nlogn*logn
1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 typedef unsigned long long ull; 16 typedef long long ll; 17 const int inf = 0x3f3f3f3f; 18 const double eps = 1e-8; 19 const int maxn = 1e4+10; 20 struct Edge 21 { 22 int to, len; 23 Edge (int _x, int _len) 24 { 25 to = _x; 26 len = _len; 27 } 28 }; 29 vector<Edge>G[maxn << 1]; 30 int siz[maxn]; 31 bool vis[maxn]; 32 void Get_size(int root, int father) 33 { 34 siz[root] = 1; 35 for (int i = 0; i < G[root].size(); i++) 36 { 37 int v = G[root][i].to; 38 if (v == father || vis[v] == true) 39 continue; 40 Get_size(v, root); 41 siz[root] += siz[v]; 42 } 43 } 44 typedef pair<int,int>pii; 45 pii FindGravity(int root, int father, int t) 46 { 47 pii res = make_pair(inf, -1); 48 int m = 0, sum = 1; 49 for (int i = 0; i < G[root].size(); i++) 50 { 51 int v = G[root][i].to; 52 if (v == father || vis[v] == true) 53 continue; 54 res = min(res, FindGravity(v, root, t)); 55 m = max(m, siz[v]); 56 sum += siz[v]; 57 } 58 m = max(m, t-sum); 59 res = min(res, make_pair(m, root)); 60 return res; 61 } 62 void Get_len(int root, int father, int d, vector<int>&len) 63 { 64 len.push_back(d); 65 for (int i = 0; i < G[root].size(); i++) 66 { 67 int v = G[root][i].to; 68 if (v == father || vis[v] == true) 69 continue; 70 Get_len(v, root, d+G[root][i].len, len); 71 } 72 } 73 int K; 74 int cnt_pair(vector<int>&ds) 75 { 76 int res = 0; 77 sort (ds.begin(), ds.end()); 78 int j = ds.size() - 1; 79 for (int i = 0; i < ds.size(); i++) 80 { 81 while (j > i && ds[i] + ds[j] > K) 82 { 83 j--; 84 } 85 res += (j > i ? j - i : 0); 86 } 87 return res; 88 } 89 int solve(int root) 90 { 91 int ans = 0; 92 Get_size(root, -1); 93 int s = FindGravity(root, -1, siz[root]).second; 94 if (s == -1) 95 return 0; 96 vis[s] = true; 97 for (int i = 0; i < G[s].size(); i++) 98 { 99 int v = G[s][i].to; 100 if (vis[v] == true) 101 continue; 102 ans += solve(v); 103 } 104 vector<int>ds; 105 ds.push_back(0); 106 for (int i = 0; i < G[s].size(); i++) 107 { 108 int v = G[s][i].to; 109 if (vis[v] == true) 110 continue; 111 vector<int>rds; 112 Get_len(v, s, G[s][i].len, rds); 113 ans -= cnt_pair(rds); 114 ds.insert(ds.end(), rds.begin(), rds.end()); 115 } 116 ans += cnt_pair(ds); 117 vis[s] = false; 118 return ans; 119 } 120 int main() 121 { 122 #ifndef ONLINE_JUDGE 123 freopen("in.txt","r",stdin); 124 #endif 125 int n; 126 while ( scanf ("%d%d", &n, &K), n && K) 127 { 128 int u, v, c; 129 for (int i = 0; i <= n; i++) 130 G[i].clear(); 131 for (int i = 0; i < n-1; i++) 132 { 133 scanf ("%d%d%d", &u, &v, &c); 134 G[u].push_back(Edge(v,c)); 135 G[v].push_back(Edge(u,c)); 136 } 137 printf("%d\n", solve(n/2+1)); 138 } 139 return 0; 140 }
②第二种姿势,,200ms左右
1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 typedef unsigned long long ull; 16 typedef long long ll; 17 const int inf = 0x3f3f3f3f; 18 const double eps = 1e-8; 19 const int maxn = 1e4+10; 20 struct Edge 21 { 22 int to, len, next; 23 }e[maxn << 1]; 24 int head[maxn], tot, N, K; 25 void add_edge(int u, int v, int c) 26 { 27 e[tot].to = v; 28 e[tot].len = c; 29 e[tot].next = head[u]; 30 head[u] = tot++; 31 } 32 int siz[maxn],Mtree[maxn]; // Mtree为最大子树的大小 siz为子树的大小 33 bool vis[maxn]; 34 int center; 35 void FindGravity(int u, int father, int cnt) // 查找重心 center 36 { 37 siz[u] = 1; 38 Mtree[u] = 0; 39 for (int i = head[u]; ~i; i = e[i].next) 40 { 41 int v = e[i].to; 42 if (v == father || vis[v] == true) 43 continue; 44 FindGravity(v, u, cnt); 45 siz[u] += siz[v]; 46 Mtree[u] = max(Mtree[u], siz[v]); 47 } 48 Mtree[u] = max(cnt - siz[u], Mtree[u]); 49 if (Mtree[center] > Mtree[u]) 50 center = u; 51 } 52 int S[maxn], dep[maxn], top; 53 void Get_len(int u, int father, int d) 54 { 55 S[top++] = d; 56 for (int i = head[u]; ~i; i = e[i].next) 57 { 58 int v = e[i].to; 59 if (vis[v] == true || v == father) 60 continue; 61 // dep[v] = dep[u] + e[i].len; 62 Get_len(v, u, d+e[i].len); 63 } 64 } 65 int Get_cnt(int u, int d) 66 { 67 int res = 0; 68 top = 0; 69 //dep[u] = d; 70 Get_len(u, 0, d); 71 sort (S, S+top); 72 int j = top - 1; 73 for (int i = 0; i < top; i++) 74 { 75 while (j > i && S[i] + S[j] > K) 76 j--; 77 res += (j > i ? j-i : 0); 78 } 79 return res; 80 } 81 int ans; 82 void solve(int r) 83 { 84 vis[r] = true; 85 ans += Get_cnt(r, 0); 86 for (int i = head[r]; ~i; i = e[i].next) 87 { 88 int v = e[i].to; 89 if (vis[v] == true) 90 continue; 91 ans -= Get_cnt(v, e[i].len); 92 center = 0; 93 FindGravity(v, r, siz[v]); 94 solve(center); 95 } 96 } 97 void init() 98 { 99 tot = 0; 100 Mtree[0] = N; 101 memset(head, -1, sizeof(head)); 102 memset(vis, false, sizeof(vis)); 103 center = 0; 104 } 105 int main() 106 { 107 #ifndef ONLINE_JUDGE 108 freopen("in.txt","r",stdin); 109 #endif 110 while (scanf ("%d%d", &N,&K), N && K) 111 { 112 init(); 113 int u, v, c; 114 for (int i = 0; i < N-1; i++) 115 { 116 scanf ("%d%d%d", &u, &v, &c); 117 add_edge(u, v, c); 118 add_edge(v, u, c); 119 } 120 ans = 0; 121 FindGravity(N/2+1, -1, N); 122 solve(center); 123 printf("%d\n", ans); 124 } 125 return 0; 126 }