LightOJ1257 Farthest Nodes in a Tree (II)(树的点分治)
题目给一棵树,边带有权值,求每一点到其他点路径上的最大权和。
树上任意两点的路径都可以看成是经过某棵子树根的路径,即路径权=两个点到根路径权的和,于是果断树分治。
对于每次分治的子树,计算其所有结点到根的距离;对于每个结点,找到另一个离根最远的且与该结点路径过根的结点,二者的距离和就是这个点在过这棵子树的根能到的最远距离。
现在问题就是怎么比较快地找到这另一个最远距离的点。。两点路径过根,说明两点间不存在一点是另一点的祖先。。我一开始还想用DFS序+线段树来着。。想了想,想出了线性的算法:
记录每个结点属于根的哪个儿子,把当前分治子树的所有结点以属于根的哪个儿子分组,对于每个结点对应过根的结点就不能在同一组要到别的组找,而且肯定是某个组里面根距离最大的值的那个结点。通过计算每个组里面结点到根的最大值作为组的值,以及这些组的最大值和次大值,就OK了。
好难描述= =反正这样这题就用树分治解决了,时间复杂度O(nlogn)。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF (1<<29)
#define MAXN 33333
struct Edge{
int u,v,w,next;
}edge[MAXN<<];
int NE,head[MAXN];
void addEdge(int u,int v,int w){
edge[NE].u=u; edge[NE].v=v; edge[NE].w=w;
edge[NE].next=head[u]; head[u]=NE++;
} bool vis[MAXN]; int size[MAXN];
void getSize(int u,int fa){
size[u]=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v] || v==fa) continue;
getSize(v,u);
size[u]+=size[v];
}
}
int centre,mini;
void getCentre(int u,int fa,int &tot){
int res=tot-size[u];
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v] || v==fa) continue;
getCentre(v,u,tot);
res=max(res,size[v]);
}
if(mini>res){
mini=res;
centre=u;
}
}
int getCentre(int u){
getSize(u,u);
mini=INF;
getCentre(u,u,size[u]);
return centre;
} int n,ans[MAXN];
int dn,dx[MAXN],dy[MAXN],mx1,mx2,belong[MAXN],mx[MAXN];
void dfs(int u,int fa,int dist,int &gp){
dx[dn]=u; dy[dn]=dist; dn++;
belong[u]=gp;
mx[gp]=max(mx[gp],dist);
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v] || v==fa) continue;
dfs(v,u,dist+edge[i].w,gp);
}
}
void conquer(int u){
dn=; mx1=; mx2=-INF;
dx[dn]=u; dy[dn]=; dn++;
belong[u]=u;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue;
mx[v]=-INF;
dfs(v,u,edge[i].w,v);
if(mx1<mx[v]) mx2=mx1,mx1=mx[v];
else if(mx2<mx[v]) mx2=mx[v];
}
for(int i=; i<dn; ++i){
if(mx[belong[dx[i]]]!=mx1) ans[dx[i]]=max(ans[dx[i]],dy[i]+mx1);
else ans[dx[i]]=max(ans[dx[i]],dy[i]+mx2);
}
} void divide(int u){
u=getCentre(u);
vis[u]=;
conquer(u);
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(vis[v]) continue;
divide(v);
}
}
int main(){
int t,a,b,c;
scanf("%d",&t);
for(int cse=; cse<=t; ++cse){
NE=;
memset(head,-,sizeof(head));
scanf("%d",&n);
for(int i=; i<n; ++i){
scanf("%d%d%d",&a,&b,&c);
addEdge(a,b,c); addEdge(b,a,c);
}
memset(vis,,sizeof(vis));
for(int i=; i<n; ++i) ans[i]=-INF;
divide();
printf("Case %d:\n",cse);
for(int i=; i<n; ++i) printf("%d\n",ans[i]);
}
return ;
}
LightOJ1257 Farthest Nodes in a Tree (II)(树的点分治)的更多相关文章
- lght oj 1257 - Farthest Nodes in a Tree (II) (树dp)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1257 跟hdu2196一样,两次dfs //#pragma comment(l ...
- lightoj 1094 Farthest Nodes in a Tree 【树的直径 裸题】
1094 - Farthest Nodes in a Tree PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: ...
- light oj 1094 Farthest Nodes in a Tree(树的直径模板)
1094 - Farthest Nodes in a Tree problem=1094" style="color:rgb(79,107,114)"> probl ...
- LightOJ 1094 - Farthest Nodes in a Tree(树的直径)
http://acm.hust.edu.cn/vjudge/contest/121398#problem/H 不是特别理解,今天第一次碰到这种问题.给个链接看大神的解释吧 http://www.cnb ...
- Farthest Nodes in a Tree ---LightOj1094(树的直径)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1094 Given a tree (a connected graph with no ...
- LightOJ1094 - Farthest Nodes in a Tree(树的直径)
http://lightoj.com/volume_showproblem.php?problem=1094 Given a tree (a connected graph with no cycle ...
- Farthest Nodes in a Tree (求树的直径)
题目链接,密码:hpu Description Given a tree (a connected graph with no cycles), you have to find the farthe ...
- lightoj1094 - Farthest Nodes in a Tree
1094 - Farthest Nodes in a Tree PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limi ...
- E - Farthest Nodes in a Tree
Given a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. Th ...
随机推荐
- WeakReference(弱引用)
原地址:http://www.cnblogs.com/bayonetxxx/archive/2009/06/02/1494728.html 我们平常用的都是对象的强引用,如果有强引用存在,GC是不会回 ...
- [BZOJ3786]星系探索
[BZOJ3786]星系探索 试题描述 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个 ...
- 如何在linux中用命令产生一个范围内的随机数?
在shell中有一个环境变量RANDOM,它的范围是0--32767 如果我们想要产生0-25范围内的数,如何做呢?如下: $RANDOM%26 用这个环境变量对26取模,就可以得到最小是0,最大是2 ...
- iPhone取消软件更新上边的1
去除设置的更新+1小红点提示主要分为越狱和非越狱设备两种方法. 越狱状态下方法: 首先将你的设备进行越狱: 越狱后安装ifile(这个自行搜索安装): 用ifile打开/System/Library/ ...
- 用nginx做反向代理来访问防外链图片
用nginx做反向代理来访问防外链图片 女儿的博客从新浪搬到wordpress后,发现原来博客上链接的新浪相册的图片都不能访问了,一年的博客内容,一个个去重新上传图片,修正链接也是个大工程.还是得先想 ...
- Python: 什么是*args和**kwargs
转自: http://blog.sina.com.cn/s/blog_65a8ab5d0101fglm.html http://blog.csdn.net/chenjinyu_tang/article ...
- 夏令时 DST (Daylight Saving Time) java中的夏令时【转】
1916年,德国首先实行夏令时,英国因为怕德国会从中得到更大的效益,因此紧跟着也采取了夏令时 1986年至1991年,中华人民共和国在全国范围实行了六年夏令时 サマータイム 夏時間(日本现在没有实行夏 ...
- HTML页面表单输入框去掉鼠标选中后边框变色的效果
标题说的有些含糊,实在不知道怎么描述了,就简单说一下吧,一个最简单的表单,代码如下,没有任何样式和名字, <!DOCTYPE html> <html> <head> ...
- Java for LeetCode 058 Length of Last Word
Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the l ...
- mysql生成varchar类型主键排序
用uuid生成20位的主键 SELECT LEFT(REPLACE(UUID(), '-', ''),20) FROM DUAL 另一种方法: 因为数据库中有字母 需要排序的时候去除字母,重新取最大值 ...