BZOJ1791: [Ioi2008]Island 岛屿

Description

你将要游览一个有N个岛屿的公园。
从每一个岛i出发,只建造一座桥。
桥的长度以Li表示。
公园内总共有N座桥。
尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走。
同时,每一对这样的岛屿,都有一艘专用的往来两岛之间的渡船。
相对于乘船而言,你更喜欢步行。
你希望所经过的桥的总长度尽可能的长,但受到以下的限制。
• 可以自行挑选一个岛开始游览。
• 任何一个岛都不能游览一次以上。
• 无论任何时间你都可以由你现在所在的岛S去另一个你从未到过的岛D。
由S到D可以有以下方法:
o 步行:仅当两个岛之间有一座桥时才有可能。
对于这种情况,桥的长度会累加到你步行的总距离;
或者
o 渡船:你可以选择这种方法,仅当没有任何桥和/或以前使用过的渡船的组合可以由S走到D(当检查是否可到达时,你应该考虑所有的路径,包括经过你曾游览过的那些岛)。
注意,你不必游览所有的岛,也可能无法走完所有的桥。
任务 编写一个程序,给定N座桥以及它们的长度,按照上述的规则,计算你可以走过的桥的最大长度。
限制 2 <= N <= 1,000,000 公园内的岛屿数目。
1<= Li <= 100,000,000 桥i的长度。

Input

• 第一行包含N个整数,即公园内岛屿的数目。
岛屿由1到N编号。
• 随后的N行每一行用来表示一个岛。
第i 行由两个以单空格分隔的整数,表示由岛i筑的桥。
第一个整数表示桥另一端的岛,第二个整数表示该桥的长度Li。
你可以假设对於每座桥,其端点总是位于不同的岛上。

Output

你的程序必须向标准输出写出包含一个整数的单一行,即可能的最大步行距离。
注1:对某些测试,答案可能无法放进32-bit整数,你要取得这道题的满分,可能需要用Pascal的int64或C/C++的long long类型。
注2:在比赛环境运行Pascal程序,由标准输入读入64-bit数据比32-bit数据要慢得多,即使被读取的数据可以32-bit表示。
我们建议把输入数据读入到32-bit数据类型。
评分 N不会超过4,000。

Sample Input

7
3 8
7 2
4 2
1 4
1 9
3 4
2 3

Sample Output

24

HINT


题解Here!

现在看到基环树就想哭。。。
我的$NOIP2018DAY2T1$啊。。。
没办法,这已经是过去了。。。
谁让我这个沙茶把自己想出来的正解给$hack$了呢。。。
还智障一样地以为自己的$hack$是对的。。。
不扯了,写题解:
题意就是给出许多基环树,求所有基环树直径的总和。
所以我们只要对每个基环树染个色,然后对每个基环树求直径就好。
但是一个基环树的直径怎么求?
我们发现,基环树的直径有两种情况:
  1. 位于某个子树中且不在环上。即:不经过环上的点。
  2. 部分经过环,且去掉处于环上的边后位于两颗不同的子树内。即:至少经过环上两个点。

所以我们得把环找出来。

同时求出:从每个环上节点出发在不经过环的前提下的最长链。

这里当然借鉴一下网上大佬得拓扑排序找环辣!

于是这个玩意直接丢给拓扑排序就好。

用求树的直径的方法更新答案处理第一种情况。

对于第二种情况,就等价于从环上找出两点$i,j$使得$dp[i]+dis(i,j)+dp[j]$最大。

$dis(i,j)$为两点在环上的最长距离。

$dp[i]$表示以$i$为根的子树内以一个端点为根的最长链。

记得考虑顺时针和逆时针两种走法。

为了快速求出$dp[i]+dis(i,j)+dp[j]$的值,我们破环成链,用单调队列优化。
附带码:
  1. #include<iostream>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #define MAXN 1000010
  5. using namespace std;
  6. int n,c=1,T=0;
  7. int head[MAXN],degree[MAXN],colour[MAXN],que[MAXN<<1];
  8. long long ans=0,dis[MAXN],dp[MAXN],f[MAXN<<1],g[MAXN<<1];
  9. bool vis[MAXN];
  10. struct Edge{
  11. int next,to,w;
  12. }a[MAXN<<1];
  13. inline int read(){
  14. int date=0,w=1;char c=0;
  15. while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
  16. while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
  17. return date*w;
  18. }
  19. inline void add(int u,int v,int w){
  20. a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
  21. a[c].to=u;a[c].w=w;a[c].next=head[v];head[v]=c++;
  22. degree[u]++;degree[v]++;
  23. }
  24. void bfs(int rt){
  25. int l=1,r=1,u,v;
  26. que[1]=rt;
  27. colour[rt]=T;
  28. while(l<=r){
  29. u=que[l];
  30. for(int i=head[u];i;i=a[i].next){
  31. v=a[i].to;
  32. if(!colour[v]){
  33. que[++r]=v;
  34. colour[v]=T;
  35. }
  36. }
  37. l++;
  38. }
  39. }
  40. void topsort(){
  41. int l=1,r=0,u,v;
  42. for(int i=1;i<=n;i++)if(degree[i]==1)que[++r]=i;
  43. while(l<=r){
  44. u=que[l];
  45. for(int i=head[u];i;i=a[i].next){
  46. v=a[i].to;
  47. if(degree[v]>1){
  48. dis[colour[u]]=max(dis[colour[u]],dp[u]+dp[v]+a[i].w);
  49. dp[v]=max(dp[v],dp[u]+a[i].w);
  50. degree[v]--;
  51. if(degree[v]==1)que[++r]=v;
  52. }
  53. }
  54. l++;
  55. }
  56. }
  57. void solve(int rt,int colour){
  58. int u,v,m=0;
  59. u=rt;
  60. for(int i=1;i;){
  61. f[++m]=dp[u];
  62. degree[u]=1;
  63. for(i=head[u];i;i=a[i].next){
  64. v=a[i].to;
  65. if(degree[v]>1){
  66. g[m+1]=g[m]+a[i].w;
  67. u=v;
  68. break;
  69. }
  70. }
  71. }
  72. if(m==2){
  73. int len=0;
  74. for(int i=head[u];i;i=a[i].next)if(a[i].to==rt)len=max(len,a[i].w);
  75. dis[colour]=max(dis[colour],dp[rt]+dp[u]+len);
  76. }
  77. else{
  78. int l=1,r=1;
  79. que[1]=1;
  80. for(int i=head[u];i;i=a[i].next)if(a[i].to==rt){
  81. g[m+1]=g[m]+a[i].w;
  82. break;
  83. }
  84. for(int i=1;i<m;i++){
  85. f[m+i]=f[i];
  86. g[m+i]=g[m+1]+g[i];
  87. }
  88. for(int i=2;i<2*m;i++){
  89. while(l<=r&&i-que[l]>=m)l++;
  90. dis[colour]=max(dis[colour],f[i]+f[que[l]]+g[i]-g[que[l]]);
  91. while(l<=r&&f[que[r]]-g[que[r]]<=f[i]-g[i])r--;
  92. que[++r]=i;
  93. }
  94. }
  95. }
  96. void work(){
  97. for(int i=1;i<=n;i++)if(degree[i]>1&&!vis[colour[i]]){
  98. vis[colour[i]]=true;
  99. solve(i,colour[i]);
  100. ans+=dis[colour[i]];
  101. }
  102. printf("%lld\n",ans);
  103. }
  104. void init(){
  105. int x,w;
  106. n=read();
  107. for(int i=1;i<=n;i++){
  108. x=read();w=read();
  109. add(i,x,w);
  110. }
  111. for(int i=1;i<=n;i++)if(!colour[i]){T++;bfs(i);}
  112. topsort();
  113. }
  114. int main(){
  115. init();
  116. work();
  117. return 0;
  118. }

BZOJ1791: [Ioi2008]Island 岛屿的更多相关文章

  1. [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)

    [bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...

  2. bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp

    1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1826  Solved: 405[Submit][S ...

  3. bzoj千题计划114:bzoj1791: [Ioi2008]Island 岛屿

    http://www.lydsy.com/JudgeOnline/problem.php?id=1791 就是求所有基环树的直径之和 加手工栈 #include<cstdio> #incl ...

  4. BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP

    题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...

  5. [BZOJ1791][IOI2008]Island岛屿(环套树DP)

    同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...

  6. bzoj1791[IOI2008]Island岛屿(基环树+DP)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...

  7. BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]

    基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...

  8. 【BZOJ 1791】 [Ioi2008]Island 岛屿

    Description 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样 ...

  9. bzoj 1791: [Ioi2008]Island 岛屿

    #include<iostream> #include<cstdio> #define M 1000009 using namespace std; *M],cnt,n,hea ...

随机推荐

  1. 【Android高级】NDK/JNI编程技术基础介绍

    作为一个Andoird的Java程序猿,会受到Java语言的局限.由于作为一面门向对象的语言不能像C/C++那样轻易调用与硬件有关的操作.因此JNI就搭建了这样一个桥梁,使Java和C/C++语言之间 ...

  2. 解决dubbo问题:forbid consumer(2)

    线下环境经常出现类似这种异常: com.alibaba.dubbo.rpc.RpcException: Forbid consumer 10.0.53.69 access service com.ku ...

  3. zoj 3888 Twelves Monkeys 二分+线段树维护次小值

    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do? problemCode=3888 Twelves Monkeys Time Limit: 5 ...

  4. NHibernate利用Mindscape.NHibernateModelDesigner实现数据库与实体之间的转换及操作

    环境: &nbsp&nbspVisual Studio 2010 一.Mindscape.NhibernateModelDesigner安装 &nbsp&nbsp在打开 ...

  5. windows上IIS实现https,配置ssl证书

    windows2012实现IIS7的https 1.申请证书,这里申请腾讯云的证书 1)登录腾讯云控制台,依次单击“云产品”>“SSL证书管理”>“申请证书” 2)在免费证书申请页面填写相 ...

  6. Squid 启动/停止/重载配置文件 命令

    当你的 squid.conf 配置文档按照你的想法修改完以后,启动 squid 之旅就开始了. Squid安装设试命令: 1,初始化你在 squid.conf 里配置的 cache 目录 #/usr/ ...

  7. MySQL四-1:数据类型

    阅读目录 一 介绍 二 数值类型 三 日期类型 四 字符串类型 五 枚举类型与集合类型 一 介绍 存储引擎决定了表的类型,而表内存放的数据也要有不同的类型,每种数据类型都有自己的宽度,但宽度是可选的 ...

  8. shell脚本中8种字符串截取方法_转自脚本之家

    转自:http://www.jb51.net/article/56563.htm 参考:http://blog.csdn.net/taiyang1987912/article/details/3955 ...

  9. Tautology - poj 3295

      Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10437   Accepted: 3963 Description WF ...

  10. Java多线程中的竞争条件、锁以及同步的概念

    竞争条件 1.竞争条件: 在java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生“竞争条件”的现象.这种现象产生的根本原因是因为多个线程在对同一个数据进行操作,此时对该数据的操作 ...