原题地址:http://poj.org/problem?id=2114

题目大意:

给定一棵点数为\(n~(n \le 10000)\)的无根树,路径上有权值,给出m组询问($m \le 100$),每组询问给出一个k,问树中是否存在长度为k的链。题目是多case

题目分析:

这是第二次写树分治,细节想清楚真的很重要啊。。。写了两天才写过,接下来说一说算法流程和需要注意的细节吧

首先读入、建图等等等等。。

然后是分治过程:

0.如果当前处理的这棵树的size很小了,调用暴力解决,否则继续执行(这相当于边界处理)

1.找出当前要处理的树的重心作为分治点

2.算出重心到这棵树中每个点的距离,扫出来是否有两个点的距离和等于要询问的值,有则加上对数

3.将重心发出的所有边断开,计算每棵子树中到重心距离和为k的点对,在答案中减去

4.递归处理所有子树,根据最终得到的个数判断是否存在

分治过程看起来很简单,但是有几个细节需要注意:断边的时候断开邻接表需要小心。每一次递归我们都需要初始化一些变量,但是每次全部初始化的代价过于高昂,而且会影响到当前树中没有的节点,每次初始化都BFS一遍过于麻烦,所有可以开若干个vector表示当前递归处理的子树中的点,然后就可以减少复杂度。计算距离之后需要排序去重以便高效地计算出要求的值。

(准备省选过于忙碌了一直没来得及写什么总结……学了不少新知识回头都得抓紧总结了)

  1 //date 20140417
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <vector>
  6
  7 const int maxn = 10500;
  8 const int INF = 0x7FFFFFFF;
  9 const int r1 = 2;
 10
 11 using namespace std;
 12 typedef vector<int> array;
 13 typedef array::iterator iter;
 14 typedef vector<array>::iterator viter;
 15
 16 inline int getint()
 17 {
 18     int ans(0); char w = getchar();
 19     while(w < '0' || '9' < w)w = getchar();
 20     while('0' <= w && w <= '9')
 21     {
 22         ans = ans * 10 + w - '0';
 23         w = getchar();
 24     }
 25     return ans;
 26 }
 27
 28 inline int innew(int &a, int b){if(a < b){a = b; return 1;}return 0;}
 29 inline int denew(int &a, int b){if(a > b){a = b; return 1;}return 0;}
 30
 31 struct edge
 32 {
 33     int v, w, next;
 34 }E[maxn << 1];
 35 int a[maxn], nedge;
 36 int n;
 37 int ask[maxn], ans[maxn], nsk;
 38
 39 vector<array> P;
 40 array tmp;
 41
 42 inline void add(int u, int v, int w)
 43 {
 44     E[++nedge].v = v;
 45     E[nedge].w = w;
 46     E[nedge].next = a[u];
 47     a[u] = nedge;
 48 }
 49
 50 namespace d_c
 51 {
 52     int yff, dis[maxn], list[maxn], size[maxn], p[maxn];
 53     int q[maxn], st, ed;
 54     int d[maxn], last, now[maxn], had[maxn];
 55     int tlist[maxn], ttot, plist[maxn];
 56
 57     inline int getcend(int k, int yff)
 58     {
 59         for(iter i = P[k].begin(); i != P[k].end(); ++i)
 60         {
 61             size[*i] = p[*i] = 0; now[*i] = a[*i];
 62         }
 63         size[d[last = 1] = P[k][0]] = 1;
 64         while(last)
 65         {
 66             int i = d[last], j = now[i];
 67             if(!j)
 68             {
 69                 if(--last) size[d[last]] += size[i];
 70                 continue;
 71             }
 72             if(!size[E[j].v])
 73             {
 74                 size[d[++last] = E[j].v] = 1;
 75                 p[E[j].v] = i;
 76             }
 77             now[i] = E[j].next;
 78         }
 79         int Max, ans, Min = INF;
 80         for(iter i = P[k].begin(); i != P[k].end(); ++i)
 81         {
 82             Max = yff - size[*i];
 83             for(int j = a[*i]; j; j = E[j].next)if(p[*i] != E[j].v)
 84                 innew(Max, size[E[j].v]);
 85             if(denew(Min, Max))ans = *i;
 86         }
 87         if(p[ans])size[p[ans]] = yff - size[ans];
 88         return ans;
 89     }
 90
 91     inline void brutf(int k, int yff)
 92     {
 93         for(iter i = P[k].begin(); i != P[k].end(); ++i)
 94         {
 95             for(iter j = P[k].begin(); j != P[k].end(); ++j)dis[*j] = list[*j] = 0;
 96             int st = 0, ed = 1, tot;
 97             q[dis[*i] = 1] = *i;
 98             while(st < ed)
 99             {
100                 int x = q[++st];
101                 for(int i = a[x]; i; i = E[i].next)if(!dis[E[i].v])
102                     dis[q[++ed] = E[i].v] = dis[x] + E[i].w;
103             }
104             for(iter j = P[k].begin(); j != P[k].end(); ++j)
105                 for(int need = 1; need <= nsk; ++need)
106                     ans[need] += (dis[*j] == ask[need] + 1) << 1;
107         }
108     }
109
110     inline void main(int k)
111     {
112         yff = P[k].size();
113         if(yff <= r1){brutf(k, yff); return;}
114         int cend = getcend(k, yff);
115         for(iter i = P[k].begin(); i != P[k].end(); ++i) dis[*i] = had[*i] = 0;
116         st = 0; ed = 1; int tot;
117         list[dis[q[1] = cend] = tot = 1] = 1;
118         while(st < ed)
119         {
120             int x = q[++st];
121             for(int i = a[x]; i; i = E[i].next)if(!dis[E[i].v])
122             {
123                 list[++tot] = dis[q[++ed] = E[i].v] = dis[x] + E[i].w;
124             }
125         }
126
127         sort(list + 1, list + tot + 1);
128         tlist[plist[1] = ttot = 1] = list[1];
129         for(int i = 2; i <= tot; ++i)
130         {
131             if(list[i] == list[i - 1])++plist[ttot];
132             else {tlist[++ttot] = list[i]; plist[ttot] = 1;}
133         }
134
135         for(int need = 1; need <= nsk; ++need)
136         {
137             int j = ttot;
138             for(int i = 1; i <= ttot; ++i)
139             {
140                 while(j && (tlist[j] + tlist[i] > ask[need] + 2))--j;
141                 if(!j)break;
142                 if(tlist[j] + tlist[i] == ask[need] + 2)
143                 {
144                     if(j != i)ans[need] += plist[i] * plist[j];
145                     else ans[need] += plist[i] * (plist[i] - 1);
146                 }
147             }
148         }
149
150         for(int i = a[cend]; i; i = E[i].next)
151         {
152             int sign = 0;
153             if(a[E[i].v] == (i ^ 1)){a[E[i].v] = E[i ^ 1].next;}
154             else
155             {
156                 int last;
157                 for(int j = a[E[i].v]; j != (i ^ 1); j = E[j].next) last = j;
158                 E[last].next = E[i ^ 1].next;
159             }
160             tmp.clear();
161             st = 0; ed = 1; q[had[E[i].v] = 1] = E[i].v;
162             tmp.push_back(E[i].v);
163             list[tot = 1] = dis[E[i].v];
164             while(st < ed)
165             {
166                 int x = q[++st];
167                 for(int j = a[x]; j; j = E[j].next)
168                     if(!had[E[j].v]){tmp.push_back(E[j].v); had[E[j].v] = 1; q[++ed] = E[j].v; list[++tot] = dis[E[j].v];}
169             }
170             sort(list + 1, list + tot + 1);
171             tlist[plist[1] = ttot = 1] = list[1];
172             for(int w = 2; w <= tot; ++w)
173             {
174                 if(list[w] == list[w - 1])++plist[ttot];
175                 else {tlist[++ttot] = list[w]; plist[ttot] = 1;}
176             }
177
178             for(int need = 1; need <= nsk; ++need)
179             {
180                 int j = ttot;
181                 for(int w = 1; w <= ttot; ++w)
182                 {
183                     while(j && (tlist[j] + tlist[w] > ask[need] + 2))--j;
184                     if(!j)break;
185                     if(tlist[w] + tlist[j] == ask[need] + 2)
186                     {
187                         if(j != w)ans[need] -= plist[w] * plist[j];
188                         else ans[need] -= plist[w] * (plist[w] - 1);
189                     }
190                 }
191             }
192
193             P.push_back(tmp);
194             main(P.size() - 1);
195         }
196
197     }
198 }
199
200 int main()
201 {
202     while(true)
203     {
204         n = getint();
205         if(!n)break;
206         P.clear(); tmp.clear();
207         memset(a, 0, sizeof a);
208         memset(ans, 0, sizeof ans);
209         nedge = 1;
210
211         for(int i = 1; i <= n; ++i)tmp.push_back(i);
212         P.push_back(tmp);
213
214         for(int i = 1; i <= n; ++i)
215         {
216             int x, w;
217             while(true)
218             {
219                 x = getint();
220                 if(!x)break;
221                 w = getint();
222                 add(i, x, w); add(x, i, w);
223             }
224         }
225         nsk = 0;
226         while(true)
227         {
228             ask[++nsk] = getint();
229             if(!ask[nsk]){--nsk; break;}
230         }
231         d_c::main(0);
232         for(int i = 1; i <= nsk; ++i)printf("%s\n", ans[i] > 0 ? "AYE" : "NAY");
233         printf(".\n");
234     }
235
236     return 0;
237 }

转载于:https://www.cnblogs.com/w007878/p/3672063.html

POJ 2114 - Boatherds相关推荐

  1. 《挑战程序设计竞赛(第2版)》习题册攻略

    本项目来源于GitHub 链接: 项目GitHub链接 1 前言 项目为<挑战程序设计竞赛(第2版)>习题册攻略,已完结.可配合书籍或笔记,系统学习算法. 题量:约200道,代码注释内含详 ...

  2. mysql 伪表查询语句_Oracle-05:伪表dual

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 此乃这张表里的全部字段信息,此表无法做修改操作 为什么有伪表这个概念?????????? 因为sql92的一个 ...

  3. app去除html标签,wap、app移动端页面常用html标签汇总

    1.section 将内容组织到精确的语义块,表示页面的一部分. 2.article article表示网页的一个文章.故事. 3.header (1)用在整页的页头 (2)section或者arti ...

  4. POJ前面的题目算法思路【转】

    1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 85% 2005-5-7 1002 487-3279 n/a 90% 2005-5- ...

  5. POJ 超详细分类

    POJ 各题算法 1000    A+B Problem            送分题     49%    2005-5-7 1001    Exponentiation         高精度   ...

  6. POJ 3268 D-Silver Cow Party

    http://poj.org/problem?id=3268 Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently ...

  7. poj 2559 Largest Rectangle in a Histogram 栈

    // poj 2559 Largest Rectangle in a Histogram 栈 // // n个矩形排在一块,不同的高度,让你求最大的矩形的面积(矩形紧挨在一起) // // 这道题用的 ...

  8. POJ 2528 Mayor's posters(线段树)

    题目大意 贴海报.每张海报的高度都是一样的,唯独宽度不一样.每张海报只能占用整数倍的单位线段长度,贴了 n(n<=10000) 张海报之后,有几张能够看见(有一个角能看见这张海报也算被看见了)? ...

  9. POJ 2226 Muddy Fields 最小点覆盖+加建图(好题)

    题目链接 题目一看就是最小点覆盖,这道题与POJ - 3041 算是一类题,但是3041算是一道十分裸的,因为删除的是整行或者整列,所以图其实是现成的,但是本题的难点就在如何建图. 思路:首先还是尽量 ...

最新文章

  1. TCP/IP协议的一个具体实现Socket
  2. 阿里公共DNS正式发布:223.5.5.5 223.6.6.6
  3. antd 获取table选中行数据_Excel数据匹配:函数法+PQ法+PB法
  4. 7-n!末尾有几个0
  5. Matlab Tricks(十九)—— 序列左右移的实现
  6. web服务器集群-------Apache网页优化 (1)网页压缩
  7. swiftui改变图片尺寸_SwiftUI中的等轴测视图
  8. Flutter Package 插件开发
  9. MapReduce 切片源码中SPLIT_SLOP等于1.1的原因分析(TextInputFormat)
  10. 弘辽科技:揭秘淘宝直通车更深层的秘密,你开对车了吗?
  11. 初步了解PS“时间轴”
  12. 2018.4.3晚_京东实习_后端开发面试记录
  13. 习题5-7 使用函数求余弦函数的近似值(15 分)
  14. 读书笔记:-----《第四次工业革命转型的力量》
  15. 作业 20180925-6 四则运算试题生成
  16. java面试宝典2013
  17. 系统集成项目管理 : 挣值管理(PV、EV、AC、SV、CV、SPI、CPI、VAC、BAC、ETC、EAC、)公式全集
  18. 【git生成私钥】git@gitlab.dfc.com: Permission denied (publickey).问题解决
  19. ipad怎么和mac分屏_iPad如何进行分屏多任务操作【详细介绍】
  20. Ubuntu下使用WonderShaper对服务器限速

热门文章

  1. 华润燃气各大区总经理_华润燃气助力空港国际新城,全面打造国家级智慧能源临空经济示范区...
  2. 【spring boot】【thymeleaf】SPEL处理 null 值
  3. 【linux】查看ip
  4. nginx 反向代理web应用将https请求转成http请求时,必须注意事项
  5. 服务器系统生产厂家,生产云服务器厂家
  6. MySQL5.5的安装,连接和操作
  7. aix卸载java,AIX系统学习之--卸载软件错误
  8. HDFS(二)HDFS架构
  9. Apache Flink 零基础入门(四)Flink开发批处理应用程序
  10. tzselect 设置时间