题目给一棵树,边带有权值,求每一点到其他点路径上的最大权和。

树上任意两点的路径都可以看成是经过某棵子树根的路径,即路径权=两个点到根路径权的和,于是果断树分治。

对于每次分治的子树,计算其所有结点到根的距离;对于每个结点,找到另一个离根最远的且与该结点路径过根的结点,二者的距离和就是这个点在过这棵子树的根能到的最远距离。

现在问题就是怎么比较快地找到这另一个最远距离的点。。两点路径过根,说明两点间不存在一点是另一点的祖先。。我一开始还想用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)(树的点分治)的更多相关文章

  1. lght oj 1257 - Farthest Nodes in a Tree (II) (树dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1257 跟hdu2196一样,两次dfs //#pragma comment(l ...

  2. lightoj 1094 Farthest Nodes in a Tree 【树的直径 裸题】

    1094 - Farthest Nodes in a Tree PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: ...

  3. light oj 1094 Farthest Nodes in a Tree(树的直径模板)

    1094 - Farthest Nodes in a Tree problem=1094" style="color:rgb(79,107,114)"> probl ...

  4. LightOJ 1094 - Farthest Nodes in a Tree(树的直径)

    http://acm.hust.edu.cn/vjudge/contest/121398#problem/H 不是特别理解,今天第一次碰到这种问题.给个链接看大神的解释吧 http://www.cnb ...

  5. Farthest Nodes in a Tree ---LightOj1094(树的直径)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1094 Given a tree (a connected graph with no ...

  6. LightOJ1094 - Farthest Nodes in a Tree(树的直径)

    http://lightoj.com/volume_showproblem.php?problem=1094 Given a tree (a connected graph with no cycle ...

  7. Farthest Nodes in a Tree (求树的直径)

    题目链接,密码:hpu Description Given a tree (a connected graph with no cycles), you have to find the farthe ...

  8. lightoj1094 - Farthest Nodes in a Tree

    1094 - Farthest Nodes in a Tree   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limi ...

  9. 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 ...

随机推荐

  1. 练习英语ing——[POJ1004]Financial Management

    [POJ1004]Financial Management 试题描述 Larry graduated this year and finally has a job. He's making a lo ...

  2. HDU3344(小广搜+小暴力

    Kakuro Extension Extension Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  3. HLG2062(make,heap问题)

    最小的n个和 Time Limit: 1000 MS Memory Limit: 32768 K Total Submit: 129(37 users) Total Accepted: 35(29 u ...

  4. 使用ifconfig命令给网卡配置ip别名

    给网卡eth0配置一个ip别名 sudo ifconfig eth0:0 10.108.125.6/22 up 若想保存该配置,以便每次开机都可以使用该ip别名,则应 sudo vim /etc/ne ...

  5. ios如何生成crash报告

    #include <signal.h> #include <execinfo.h> void OnProcessExceptionHandler(int sigl) { do ...

  6. iOS8 UILocalNotification 和 UIRemoteNotification 使用注意 草稿,正在整理中。。。。

    先说一个关于UILocalNotification的知识点,容易被忘记: Each app on a device is limited to 64 scheduled local notificat ...

  7. TinyXML 在vs2010 VC++使用

    1.下载TinyXML  http://www.grinninglizard.com/tinyxml/  解压缩,将以下六个文件复制到您的工程项目文件(跟您的cpp文件在一个目录下)中 tinyxml ...

  8. vs 附加包含目录属性

    如果是在属性页里头添加了路径,则当程序拷贝到其他电脑上头的话,这个包含目录仍然存在,这就是与添加环境变量的区别.如果是通过添加环境变量配置的路径,则换了台电脑,这个路径就没有了,需要重新配置.

  9. 解决 mysql 启动报错--发现系统错误2,系统找不到指定的文件

    HKEY_LOCAL_MACHINE-SYSTEM-CurrentControlSet-services-mysql(服务名)-ImagePath 更改为(自己的):"C:\Program ...

  10. 前端代理nproxy

    一.场景/用途 前端代理的用途,相信大家都清楚.应用场景很多,如—— . 将线上的静态资源文件(JS.CSS.图片)替换为本地相应的文件,来调试线上(代码都被压缩过)的问题: . 本地开发过程,当后端 ...