【BZOJ3302】[Shoi2005]树的双中心

Description

Input

第一行为N,1<N<=50000,表示树的节点数目,树的节点从1到N编号。
接下来N-1行,每行两个整数U,V,表示U与V之间有一条边。
再接下N行,每行一个正整数,其中第i行的正整数表示编号为i的节点权值为W(I),树的深度<=100

Output

将最小的S(x,y)输出,结果保证不超过19^9

Sample Input

5
1 2
1 3
3 4
3 5
5
7
6
5
4

Sample Output

14

HINT

选取两个中心节点为2,3

题解:这题的做法还是挺神的~

有一种暴力的方法:先枚举一条边,将这条边断开,然后两边分别求重心,但是这样做复杂度有点高。

如何优化呢?观察到树高只有300,所以我们可以从树根开始,不断向靠近重心的方向移动,不能移动时就找到了重心,复杂度是树高级别的,可以通过此题。

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. using namespace std;
  5. const int maxn=50010;
  6. typedef long long ll;
  7. int n,cnt;
  8. int head[maxn],to[maxn<<1],next[maxn<<1],fa[maxn],ins[maxn];
  9. ll siz[maxn],f[maxn][2],g[maxn];
  10. ll tot,now,ans,sz;
  11. inline void add(int a,int b)
  12. {
  13. to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
  14. }
  15. inline ll rd()
  16. {
  17. ll ret=0,f=1; char gc=getchar();
  18. while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
  19. while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
  20. return ret*f;
  21. }
  22. void dfs1(int x)
  23. {
  24. for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x])
  25. {
  26. fa[to[i]]=x,dfs1(to[i]),siz[x]+=siz[to[i]],g[x]+=g[to[i]]+siz[to[i]];
  27. if(siz[to[i]]>siz[f[x][0]]) f[x][1]=f[x][0],f[x][0]=to[i];
  28. else f[x][1]=(siz[f[x][1]]>siz[to[i]])?f[x][1]:to[i];
  29. }
  30. }
  31. inline ll calc(int x,int y)
  32. {
  33. ll sy=siz[y]-(ins[y])*sz;
  34. return now-2*sy+tot;
  35. }
  36. void dfs3(int x)
  37. {
  38. ll t1=calc(x,f[x][0]),t2=calc(x,f[x][1]);
  39. if(t1<t2)
  40. {
  41. if(t1<now) now=t1,dfs3(f[x][0]);
  42. }
  43. else if(t2<now) now=t2,dfs3(f[x][1]);
  44. }
  45. void dfs2(int x,int dep)
  46. {
  47. ins[x]=1;
  48. if(x!=1)
  49. {
  50. ll tmp=0;
  51. tot=siz[x],sz=0,now=g[x],dfs3(x),tmp+=now;
  52. tot=siz[1]-siz[x],sz=siz[x],now=g[1]-g[x]-dep*siz[x],dfs3(1),tmp+=now;
  53. ans=min(ans,tmp);
  54. }
  55. for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa[x]) dfs2(to[i],dep+1);
  56. ins[x]=0;
  57. }
  58. int main()
  59. {
  60. n=rd();
  61. int i,a,b;
  62. memset(head,-1,sizeof(head));
  63. for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
  64. for(i=1;i<=n;i++) siz[i]=rd();
  65. dfs1(1),ans=g[1],dfs2(1,0);
  66. printf("%lld",ans);
  67. return 0;
  68. }

【BZOJ3302】[Shoi2005]树的双中心 DFS的更多相关文章

  1. BZOJ3302: [Shoi2005]树的双中心

    BZOJ3302: [Shoi2005]树的双中心 https://lydsy.com/JudgeOnline/problem.php?id=3302 分析: 朴素算法 : 枚举边,然后在两个连通块内 ...

  2. 题解-SHOI2005 树的双中心

    SHOI2005 树的双中心 给树 \(T=(V,E)(|V|=n)\),树高为 \(h\),\(w_u(u\in V)\).求 \(x\in V,y\in V:\left(\sum_{u\in V} ...

  3. 【BZOJ】3302: [Shoi2005]树的双中心 && 2103: Fire 消防站 && 2447: 消防站

    [题意]给定带点权树,要求选择两个点x,y,满足所有点到这两个点中较近者的距离*点权的和最小.n<=50000,h<=100. [算法]树的重心 [题解]代码参考自:cgh_Andy 观察 ...

  4. luogu P2726 [SHOI2005]树的双中心

    传送门 强行安利->巨佬题解 如果只有一个点贡献答案,那么答案显然是这棵树的带权重心,这个是可以\(O(n)\)求的.一个\(O(n^2)\)暴力是枚举两个集合之间的分界边,然后对这两个集合分别 ...

  5. [SHOI2005]树的双中心

    题目链接:Click here Solution: 首先我们要知道,选择两个点\(A,B\),必定存在一条边,割掉这条边,两个集合分别归\(A,B\)管 再结合题目,我们就得到了一个暴力的\(n^2\ ...

  6. 【洛谷 P2726】 [SHOI2005]树的双中心(树的重心)

    先考虑一个\(O(N^2)\)做法. 设选的两个点为\(x,y\),则一定可以将树分成两个集合\(A,B\),使得\(A\)集合所有点都去\(x\),\(B\)集合所有点都去\(y\),而这两个集合的 ...

  7. bzoj 3302&2447&2103 树的双中心 树形DP

    题目: 题解: bzoj 3302 == 2447 == 2103 三倍经验 首先我们考虑枚举两个中心的位置,然后统计答案. 我们发现,一定有一部分点离第一个中心更近,另一部分点离第二个中心更近 如果 ...

  8. HDU 4602 Magic Ball Game(离线处理,树状数组,dfs)

    Magic Ball Game Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  9. Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序

    Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...

随机推荐

  1. 对tensorflow 中的attention encoder-decoder模型调试分析

    #-*-coding:utf8-*- __author = "buyizhiyou" __date = "2017-11-21" import random, ...

  2. 浙大PAT考试1077~1080(2014上机复试题目)

    题目地址:点击打开链接 还是太弱. . 英文太差.,, 预计要等待被虐了.. 1077 找最长的公共后缀,暴力就能够写: #include<iostream> #include<cs ...

  3. Python转码问题的解决方法

    FROM: http://www.jb51.net/article/16104.htm 在Python中,可以对String调用decode和encode方法来实现转码.     比如,若要将某个St ...

  4. go语言编程小tips

    go语言一个比较方便的特性是你不需要显示的定义一个变量.例如,在c语言中,你想要使用一个int型变量,那么代码如下 int i; i =0; i++; 而在go语言中, i := 0; i++ 这样你 ...

  5. Maven够用就好

    学习maven.仅仅要知道pom.dependency.coordination就能够了,剩下的就是学习一个一个的plugin的Goal 配置maven 下载    http://maven.apac ...

  6. 使用终端shell命令批量改动一个文件下的全部文件的读写权限

    之前对openfire安装的目录就遇到过这个问题,今天再次遇到.须要改动一个目录以下的全部子目录以及文件的三个权限:本用户读写.管理员读写.全部人读写,三个都要需改为wr 步骤例如以下:比如我要改动/ ...

  7. MPTCP 理解

    背景      随着技术的发展许多设备具有了多个网络接口,而TCP依然是一个单线路的协议,在TCP的通信过程中发端和收端都 不能随意变换地址.我们可以利用多个网络接口的这一特性来改善性能和有效冗余.例 ...

  8. 怎么运行Typescript

    依据官方示例: npm i -g typescript 示例:tsc *.ts 实例:tsc hello.ts 不过以上实现的太有限制了,如下实现可满足正常测试以及学习使用 package,json ...

  9. DNS检测

    dig @58.241.41.152 6900255264940.barcode.cniotroot.cn naptr 没有naptr 好像有点异常 select count(*) as total ...

  10. 使用Cocos studio创建一个简单的project

    前不久我接到了一个项目,项目要求使用Cocos2d-X的最新版本号,Cocos2d-X3.4.对于一直在陶醉在Cocos2d-X2.2.3的世界中的我开说,使用Cocos2d-X3.4忽然认为有点不适 ...