poj2114(树的点分治)
来源:互联网 发布:当代文学论文选题知乎 编辑:程序博客网 时间:2024/06/05 23:03
参考文章: http://blog.csdn.net/yang_7_46/article/details/9966455
题目的大致意思是要求出是否存在两点间的路径长度为K的情况
不知道为什么1741一直是re,主要还是看别人文章学习来的树的点分治。
点分治,主要是分类来进行处理,对于两点之前求距离可以分为两类情况:
1.过根节点(不在一棵子树内)
2.不过根节点(在同一棵子树内)
第2种情况可以通过递归转化成第1种情况,对于第1种情况,求出到根节点的距离dis,然后它们之前的距离就为dis[i] + dis[j],对于求满足的情况,有个比较巧妙的办法,就是对其排序之后,然后在O(n)的时间内找到,主要还是在对1741的时候作用比较大(1741是要求距离小于等于K,2114是要求刚好等于K)
另外对于树而言,要求其重心(树的最大深度的值最小),这样在计算的时候可以避免出现类似一条链的情况。
//得到重心void getRoot(int now, int fa){//s代表树中点的个数,f代表它的深度s[now] = 1; f[now] = 0;for(int k = head[now]; k != -1; k = edge[k].next){//如果访问过,或者是其父节点if( fa == edge[k].t || visit[edge[k].t]) continue;getRoot(edge[k].t, now);s[now] += s[edge[k].t];f[now] = max(f[now], s[edge[k].t]);}f[now] = max(f[now], size - s[now]);if( f[now] < f[root] )root = now;}
<pre name="code" class="cpp">//得到距离根的距离void getD(int now, int fa){dep.push_back(d[now]);s[now] = 1;for(int k = head[now]; k != -1; k = edge[k].next){if( edge[k].t == fa || visit[edge[k].t] ) continue;d[edge[k].t] = d[now] + edge[k].w;getD(edge[k].t, now);s[now] += s[edge[k].t];}}//计算个数int calc(int now, int dis){dep.clear();d[now] = dis;getD(now,0);sort(dep.begin(), dep.end());int ret = 0, l = 0, r = dep.size() - 1;while( l < r ){if (dep[l] + dep[r] == K) { if (dep[l] == dep[r]) { ret += (r-l+1)*(r-l)/2; break; } int i=l, j=r; while (dep[i] == dep[l]) i++; while (dep[j] == dep[r]) j--; ret += (i-l)*(r-j); l = i, r = j; } else if (dep[l] + dep[r] < K) l++; else r--; }return ret;}void work(int temp){ans += calc(temp,0);visit[temp] = true;for(int k = head[temp]; k != -1; k = edge[k].next){if( visit[edge[k].t] ) continue;ans -= calc(edge[k].t, edge[k].w);f[0] = size = s[edge[k].t];getRoot(edge[k].t, root = 0);work(root);}}void solve(){Mem(head, -1);int u,w;kNum = 0;for(int i = 1; i <= n; i ++){while(cin>>u && u){cin>>w;addEdge(i, u, w);addEdge(u, i, w);}}while(cin>>K && K){Mem(visit,false);f[0] = size = n;getRoot(1, root = 0);ans = 0;work(root);printf("%s\n",ans > 0 ? "AYE" : "NAY" );}printf(".\n");}
0 0
- poj2114(树的点分治)
- [树的点分治] [POJ2114] Boatherds
- POJ2114 Boatherds 点分治
- 【POJ2114】Boatherds 树分治
- POJ2114【树分治】
- POJ2114(树分治)
- 点分治练习poj1741;poj2114;bzoj2599
- [POJ2114]Boatherds(点分治+二分)
- 树的分治-点分治
- 树的点分治
- 树的点分治
- POJ1741树的分治之点分治
- 树分治-点分治
- poj1741 树的点分治
- 树基于点的分治
- 【树的点分治】阴阳
- CV1873 树的点分治
- 浅谈树的点分治
- RAC环境维护常用命令
- Android WebView 缓存处理
- android中图片的三级缓存cache策略(内存/文件/网络)
- Android入门:封装一个HTTP请求的辅助类
- 点菜问题_1152
- poj2114(树的点分治)
- EXTJS动态树,非常完整的一个例子
- 选择图片
- 二维数组——数字查找
- zabbix 监控端口和进程
- java调用sql存储过程
- strtok、strtok_s、strtok_r 字符串分割函数
- python网页爬虫之列车时刻表的抓取(4)-完整的python脚本
- [自学Android之旅] 获取通讯录的联系人 姓名和号码