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 ...
随机推荐
- java笔记--用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程
用ThreadLocal管理线程,Callable<V>接口实现有返回值的线程 ThreadLocal在我的笔记"关于线程同步"的第5种方式里面有介绍,这里就不多说了. ...
- Android ADB命令大全(通过ADB命令查看wifi密码、MAC地址、设备信息、操作文件、查看文件、日志信息、卸载、启动和安装APK等)
ADB很强大,记住一些ADB命令有助于提高工作效率. 获取序列号: adb get-serialno 查看连接计算机的设备: adb devices 重启机器: adb reboot 重启到bootl ...
- JS匿名函数的理解
js匿名函数的代码如下:(function(){ // 这里忽略jQuery 所有实现 })(); 半年前初次接触jQuery 的时候,我也像其他人一样很兴奋地想看看源码是什么样的.然而,在看到源码的 ...
- docker的四种网络模式
/* 1. host模式 : docker run 使用 --net=host指定 docker使用的网络实际上和宿主机一样 2. container模式: 使用 --net=container:co ...
- Android 中的Resource
Android与ios相比,各种各样Resource算个独特之处.详情请参见官网Resource Types Resource有许多种,常见的有图像资源,布局资源,等等.每一种资源的位置都是固定的,这 ...
- MinGW/MSYS 交叉编译环境搭建
因为包的依赖关系不清楚,搭建时出错也不知道是什么原因,下面链接老外写的搭建步骤,写的非常详细还有脚本 已经编译的下载地址 http://ingar.satgnu.net/devenv/mingw32/ ...
- codeforces A. Strange Addition 解题报告
题目链接:http://codeforces.com/problemset/problem/305/A 题目意思:给出一个序列,需要从中选择一些数,这些数需要满足:任意的两个数中每一位至少有一个数满足 ...
- 部署django应用
Autor: wangxianlong 2016/7/10 16:17:55 环境: centos 6.5 python 2.7.5 django 1.9 nginx 1.8 selinux diab ...
- OpenGL在 win8 64bits系统下的配置
1 program files(x86)与program files 在64位系统下,为了更好的兼容32位程序,在安装一些32位程序(注意某些程序他就是32位的),会默认扔到program files ...
- fedora yum 使用代理的方法
配置yum: 编辑/etc/yum.conf添加下列一行: proxy=http://domain/user:passwd@<proxy ip>:80 <proxy ip>:代 ...