POJ 2114 - Boatherds
原题地址: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相关推荐
- 《挑战程序设计竞赛(第2版)》习题册攻略
本项目来源于GitHub 链接: 项目GitHub链接 1 前言 项目为<挑战程序设计竞赛(第2版)>习题册攻略,已完结.可配合书籍或笔记,系统学习算法. 题量:约200道,代码注释内含详 ...
- mysql 伪表查询语句_Oracle-05:伪表dual
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 此乃这张表里的全部字段信息,此表无法做修改操作 为什么有伪表这个概念?????????? 因为sql92的一个 ...
- app去除html标签,wap、app移动端页面常用html标签汇总
1.section 将内容组织到精确的语义块,表示页面的一部分. 2.article article表示网页的一个文章.故事. 3.header (1)用在整页的页头 (2)section或者arti ...
- POJ前面的题目算法思路【转】
1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 85% 2005-5-7 1002 487-3279 n/a 90% 2005-5- ...
- POJ 超详细分类
POJ 各题算法 1000 A+B Problem 送分题 49% 2005-5-7 1001 Exponentiation 高精度 ...
- POJ 3268 D-Silver Cow Party
http://poj.org/problem?id=3268 Description One cow from each of N farms (1 ≤ N ≤ 1000) conveniently ...
- poj 2559 Largest Rectangle in a Histogram 栈
// poj 2559 Largest Rectangle in a Histogram 栈 // // n个矩形排在一块,不同的高度,让你求最大的矩形的面积(矩形紧挨在一起) // // 这道题用的 ...
- POJ 2528 Mayor's posters(线段树)
题目大意 贴海报.每张海报的高度都是一样的,唯独宽度不一样.每张海报只能占用整数倍的单位线段长度,贴了 n(n<=10000) 张海报之后,有几张能够看见(有一个角能看见这张海报也算被看见了)? ...
- POJ 2226 Muddy Fields 最小点覆盖+加建图(好题)
题目链接 题目一看就是最小点覆盖,这道题与POJ - 3041 算是一类题,但是3041算是一道十分裸的,因为删除的是整行或者整列,所以图其实是现成的,但是本题的难点就在如何建图. 思路:首先还是尽量 ...
最新文章
- TCP/IP协议的一个具体实现Socket
- 阿里公共DNS正式发布:223.5.5.5 223.6.6.6
- antd 获取table选中行数据_Excel数据匹配:函数法+PQ法+PB法
- 7-n!末尾有几个0
- Matlab Tricks(十九)—— 序列左右移的实现
- web服务器集群-------Apache网页优化 (1)网页压缩
- swiftui改变图片尺寸_SwiftUI中的等轴测视图
- Flutter Package 插件开发
- MapReduce 切片源码中SPLIT_SLOP等于1.1的原因分析(TextInputFormat)
- 弘辽科技:揭秘淘宝直通车更深层的秘密,你开对车了吗?
- 初步了解PS“时间轴”
- 2018.4.3晚_京东实习_后端开发面试记录
- 习题5-7 使用函数求余弦函数的近似值(15 分)
- 读书笔记:-----《第四次工业革命转型的力量》
- 作业 20180925-6 四则运算试题生成
- java面试宝典2013
- 系统集成项目管理 : 挣值管理(PV、EV、AC、SV、CV、SPI、CPI、VAC、BAC、ETC、EAC、)公式全集
- 【git生成私钥】git@gitlab.dfc.com: Permission denied (publickey).问题解决
- ipad怎么和mac分屏_iPad如何进行分屏多任务操作【详细介绍】
- Ubuntu下使用WonderShaper对服务器限速
热门文章
- 华润燃气各大区总经理_华润燃气助力空港国际新城,全面打造国家级智慧能源临空经济示范区...
- 【spring boot】【thymeleaf】SPEL处理 null 值
- 【linux】查看ip
- nginx 反向代理web应用将https请求转成http请求时,必须注意事项
- 服务器系统生产厂家,生产云服务器厂家
- MySQL5.5的安装,连接和操作
- aix卸载java,AIX系统学习之--卸载软件错误
- HDFS(二)HDFS架构
- Apache Flink 零基础入门(四)Flink开发批处理应用程序
- tzselect 设置时间