码迷,mamicode.com
首页 > 其他好文 > 详细

男人八题_POJ-1741

时间:2015-02-08 11:29:13      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://poj.org/problem?id=1741

树分治相关论文:http://wenku.baidu.com/view/60c6aa1ffc4ffe473368aba8.html

由于论文中有该题的讲解,所以便不再赘述。代码如下

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 #define lowbit(a) ((a)&(-a))
  7 #define max(a, b) ((a)>(b)?(a):(b))
  8 #define min(a, b) ((a)<(b)?(a):(b))
  9 #define MAXN 10010
 10 #define MAXM 20010
 11 #define PI 3.1415926
 12 #define E 2.718281828
 13 #define INF 0x777777f
 14 typedef long long LL;
 15 
 16 int eCnt, fir[MAXN]; struct edge{int v, w, nxt;} eg[MAXM];
 17 int n, k, ans, q[MAXN], size[MAXN], maxx[MAXN], vis[MAXN], dis[MAXN];
 18 
 19 void addedge(int u, int v, int w){
 20     eg[++eCnt].v = v; eg[eCnt].w = w;
 21     eg[eCnt].nxt = fir[u]; fir[u] = eCnt;
 22 }
 23 void init(){
 24     eCnt = ans = 0;
 25     for (int i = 0; i <= n; i++){
 26         vis[i] = fir[i] = 0;
 27     }
 28 }
 29 /*找出树的重心*/
 30 int bfs_root(int u){
 31     int h = 1, t = 1, ret = 0; maxx[0] = INF;
 32     q[t] = u; maxx[u] = 0; size[u] = 1; vis[u] = 2;
 33     for ( ; h <= t; h++){
 34         for (int u = q[h], e = fir[u]; e != 0; e = eg[e].nxt){
 35             if (!vis[eg[e].v]){
 36                 vis[eg[e].v] = 2;
 37                 q[++t] = eg[e].v;
 38                 size[eg[e].v] = 1;
 39                 maxx[eg[e].v] = 0;
 40             }
 41         }
 42     }
 43     for (h--; h > 0; h--){
 44         int u = q[h];
 45         vis[u] = 0;
 46         for (int e = fir[u]; e != 0; e = eg[e].nxt){
 47             if (!vis[eg[e].v]){
 48                 size[u] += size[eg[e].v];
 49                 maxx[u] = max(maxx[u], size[eg[e].v]);
 50             }
 51         }
 52         maxx[u] = max(t-size[u], maxx[u]);
 53         if (maxx[u] < maxx[ret]) ret = u;
 54     }
 55     return ret;
 56 }
 57 /*预处理root到子节点的距离*/
 58 int dfs_dis(int u){
 59     int h = 1, t = 1;
 60     q[t] = u; dis[t] = 0; vis[u] = 2;
 61     for ( ; h <= t; h++){
 62         for (int u = q[h], e = fir[u]; e != 0; e = eg[e].nxt){
 63             if (!vis[eg[e].v]){
 64                 vis[eg[e].v] = 2;
 65                 q[++t] = eg[e].v;
 66                 dis[t] = dis[h] + eg[e].w;
 67             }
 68         }
 69     }
 70     for (h = 1; h <= t; h++) vis[q[h]] = 0;
 71     return t;
 72 }
 73 /*计算满足长度小于k且经过u的路径的数量,且路径可以不合法*/
 74 int dfs_calc(int u, int k){
 75     int num = dfs_dis(u), ret = 0;
 76     sort(dis+1, dis+1+num);
 77     for (int i = 1, j = num; i < j; i++){
 78         for ( ; dis[i] + dis[j] > k; j--)
 79             if (i == j) break;
 80         ret += j - i;
 81     }
 82     return ret;
 83 }
 84 /*点分治*/
 85 void dfs(int u){
 86     int root = bfs_root(u);
 87     ans += dfs_calc(root, k);
 88     vis[root] = 1;
 89     for (int e = fir[root]; e != 0; e = eg[e].nxt){
 90         int v = eg[e].v;
 91         if (vis[v]) continue;
 92         ans -= dfs_calc(v, k-eg[e].w*2);
 93         dfs(v);
 94     }
 95 }
 96 int main(){
 97     int u, v, w;
 98     for ( ; ; ){
 99         init();
100         scanf("%d%d", &n, &k);
101         if (n == 0 && k == 0) break;
102         for (int i = 1; i < n; i++){
103             scanf("%d%d%d", &u, &v, &w);
104             addedge(u, v, w);
105             addedge(v, u, w);
106         }
107         dfs(1);
108         printf("%d\n", ans);
109     }
110     return 0;
111 }

 

男人八题_POJ-1741

标签:

原文地址:http://www.cnblogs.com/zhu8655/p/4279755.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!