Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 11229 | Accepted: 3515 |
Description
Input
Output
Sample Input
5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0
Sample Output
8
Source
#include <map> #include <set> #include <list> #include <stack> #include <queue> #include <vector> #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int N = 10010; const int inf = 0x3f3f3f3f; int num[N]; int head[N]; int dist[N]; int dp[N]; bool vis[N]; struct node { int weight; int next; int to; }edge[N << 1]; int tot, root, n, k, size, res, ans; void addedge(int from, int to, int weight) { edge[tot].weight = weight; edge[tot].to = to; edge[tot].next = head[from]; head[from] = tot++; } void get_root(int u, int fa) { num[u] = 1; dp[u] = 0; for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa || vis[v]) //-------------------------A { continue; } get_root(v, u); num[u] += num[v]; dp[u] = max(dp[u], num[v]); } dp[u] = max(dp[u], size - num[u]); if (dp[u] < dp[root]) { root = u; } } void calc_dist(int u, int fa, int d) { dist[res++] = d; for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa || vis[v])//--------------------------B { continue; } calc_dist(v, u, d + edge[i].weight); } } int counts(int u, int d) { res = 0; calc_dist(u, -1, d); int ans = 0; sort(dist, dist + res); int i = 0; int j = res - 1; while (i < j) { while (i < j && dist[i] + dist[j] > k) { j--; } ans += j - i; i++; } return ans; } void solve(int u) { ans += counts(root, 0); vis[root] = 1; for (int i = head[root]; ~i; i = edge[i].next) { int v = edge[i].to; if (vis[v]) { continue; } ans -= counts(v, edge[i].weight); // ------------------------------C root = 0; dp[0] = size = num[v]; get_root(v, -1); solve(v); } } int main() { int u, v, w; while (~scanf("%d%d", &n, &k)) { if (!n && !k) { break; } memset ( head, -1, sizeof(head) ); memset ( num, 0, sizeof(num) ); memset ( vis, 0, sizeof(vis) ); tot = 0; ans = 0; for (int i = 0; i < n - 1; ++i) { scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); addedge(v, u, w); } root = 0; dp[root] = size = n; get_root(1, -1); solve(1); printf("%d\n", ans); } return 0; }
ans -= counts(v, edge[i].weight);为什么是edge[i].weight而不是0,今天看的时候不知道是不是脑子短路了一直没理解,其实是这样的,root(当前树根)这棵树统计完了点对以后,其实已经包含了某些点对,它们处在同一个子树里,但是距离和确实小于等于k的,那么这里小于等于k是基于它们到点root的,所以在处理v这个子树的时候,我们需要把这样的点对给去掉,那么基准点当然还是以root为主,这样才能准确地去掉这些点对,所以要加上root --- v这条边上的权值