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

题解:基环树DP写的很少……

树的直径不用解释了,就是NOIP2018D1T3的20分做法,基环树直径,我们可以yy一下然后就能发现答案是2种:1、把环剖去以后其余的子树的直径。2、环上的一部分+选中的2点中各自的最长链。

第一种可以直接dfs求解,对于第二种……我们可以摒弃垃圾的dfs两遍求树的直径的做法,改成DP形式的求树的直径。然后找到一个环时,记录环上的点最深的深度,然后可以把这个环扩展,记录l,r指针,扫描,随便搞一下就能求得答案。

所以本蒟蒻想到的具体做法就是:先topsort一下,把环给找出来,边topsort边DP,然后遇到环再dfs就OK了

不说废话看代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e6+;
int n,cnt,tim,hd[N],v[N],nxt[N],w[N],c[N],du[N],vis[N],q[N];
ll ans,d[N],f[N],a[N],b[N];
void add(int x,int y,int z){v[++cnt]=y,nxt[cnt]=hd[x],hd[x]=cnt,w[cnt]=z;}
void dfs(int u,int k)
{
c[u]=k;
for(int i=hd[u];i;i=nxt[i])if(!c[v[i]])dfs(v[i],k);
}
void topsort()
{
int qs=,qe=;
for(int i=;i<=n;i++)if(du[i]==)q[qe++]=i;
while(qs<qe)
{
int u=q[qs++];
for(int i=hd[u];i;i=nxt[i])
if(du[v[i]]>)
{
du[v[i]]--;
d[c[u]]=max(d[c[u]],f[u]+f[v[i]]+w[i]);
f[v[i]]=max(f[v[i]],f[u]+w[i]);
if(du[v[i]]==)q[qe++]=v[i];
}
}
}
void dp(int x,int tp)
{
int m=,y=x,i;
do{
a[++m]=f[y];
du[y]=;
for(i=hd[y];i;i=nxt[i])
if(du[v[i]]>){b[m+]=b[m]+w[i];y=v[i];break;}
}while(i);
if(m==)
{
int len=;
for(int i=hd[y];i;i=nxt[i])if(v[i]==x)len=max(len,w[i]);
d[tp]=max(d[tp],f[x]+f[y]+len);
return;
}
for(int i=hd[y];i;i=nxt[i])if(v[i]==x){b[m+]=b[m]+w[i];break;}
for(int i=;i<=m;i++)a[m+i]=a[i],b[m+i]=b[m+]+b[i];
int l=,r=;
l=r=q[]=;
for(int i=;i<*m;i++)
{
while(l<=r&&i-q[l]>=m)l++;
d[tp]=max(d[tp],b[i]-b[q[l]]+a[i]+a[q[l]]);
while(l<=r&&a[q[r]]+b[i]-b[q[r]]<=a[i])r--;
q[++r]=i;
}
}
int main()
{
scanf("%d",&n);
for(int i=,x,y;i<=n;i++)scanf("%d%d",&x,&y),add(i,x,y),add(x,i,y),du[x]++,du[i]++;
for(int i=;i<=n;i++)if(!c[i])dfs(i,++tim);
topsort();
for(int i=;i<=n;i++)
if(du[i]>&&!vis[c[i]])vis[c[i]]=,dp(i,c[i]),ans+=d[c[i]];
printf("%lld",ans);
}

bzoj1791[IOI2008]Island岛屿(基环树+DP)的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 1791: [IOI2008]Island 岛屿 - 基环树

    传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无 ...

  6. BZOJ1791: [Ioi2008]Island 岛屿

    BZOJ1791: [Ioi2008]Island 岛屿 Description 你将要游览一个有N个岛屿的公园. 从每一个岛i出发,只建造一座桥. 桥的长度以Li表示. 公园内总共有N座桥. 尽管每 ...

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

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

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

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

  9. P4381 [IOI2008]Island(基环树+单调队列优化dp)

    P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...

随机推荐

  1. 微服务架构中APIGateway原理

    背景 我们知道在微服务架构风格中,一个大应用被拆分成为了多个小的服务系统提供出来,这些小的系统他们可以自成体系,也就是说这些小系统可以拥有自己的数据库,框架甚至语言等,这些小系统通常以提供 Rest ...

  2. react 入坑笔记(一)

    一些概念: 1.组件:概念等同于 vue 中的组件,字面意思,不过 vue 中组件是以 .vue 结尾,通过 vue-loader 编译成 js,而 react 组件就是 js. 2.jsx:js 语 ...

  3. oracle逗号分隔函数

    SELECT wm_concat(GZTYPE) str FROM TB_FDN_WORKKIND

  4. Directory of X:\EFI\Microsoft\Boot

    Directory of X:\EFI\Microsoft\Boot 2017/06/21 15:14 <DIR> . 2017/06/21 15:14 <DIR> .. 20 ...

  5. Web API2 使用默认Identity

    当您选择个人账户在Web API项目模板,项目包含一个令牌授权服务器验证用户凭证和问题.下面的图显示了相同的凭证流的Web API组件. 发送一个未经授权的请求 首先,运行应用程序并单击按钮调用的AP ...

  6. Codeforces Round #475 Div. 1

    B:当n是偶数时无解,因为此时树中有奇数条边,而我们每次都只能删除偶数条.当n是奇数时一定有解,因为此时不可能所有点度数都为奇数,只要找到一个度数为偶数的点,满足将它删掉后,各连通块大小都为奇数就可以 ...

  7. Colored Sticks POJ - 2513 并查集+欧拉通路+字典树hash

    题意:给出很多很多很多很多个棒子 左右各有颜色(给出的是单词) 相同颜色的可以接在一起,问是否存在一种 方法可以使得所以棒子连在一起 思路:就是一个判欧拉通路的题目,欧拉通路存在:没奇度顶点   或者 ...

  8. 洛谷P1007独木桥题解

    题目 这个题看起来很难,但是只要理解了题目,一切都显得简单. 你只需想象出来每个人在碰撞之后仅仅是交换了灵魂, 这样一来,代码就好写了. 附代码: #include<iostream> # ...

  9. Matplotlib学习---用seaborn画矩阵图(pair plot)

    矩阵图非常有用,人们经常用它来查看多个变量之间的联系. 下面用著名的鸢尾花数据来画一个矩阵图.从sklearn导入鸢尾花数据,然后将其转换成pandas的DataFrame类型,最后用seaborn画 ...

  10. 【题解】 bzoj2462: [BeiJing2011]矩阵模板

    题面戳我 Solution 二维矩阵\(hash\),判断即可 自己YY了一个方法,\(bzoj\)T到飞,(一开始还用的三\(hash\)),交到luogu貌似跑的不慢啊qwq (我是不会告诉你全输 ...