BZOJ1791: [Ioi2008]Island 岛屿
Description
Input
Output
Sample Input
3 8
7 2
4 2
1 4
1 9
3 4
2 3
Sample Output
HINT

题解Here!
- 位于某个子树中且不在环上。即:不经过环上的点。
- 部分经过环,且去掉处于环上的边后位于两颗不同的子树内。即:至少经过环上两个点。
所以我们得把环找出来。
同时求出:从每个环上节点出发在不经过环的前提下的最长链。
这里当然借鉴一下网上大佬得拓扑排序找环辣!
于是这个玩意直接丢给拓扑排序就好。
用求树的直径的方法更新答案处理第一种情况。
对于第二种情况,就等价于从环上找出两点$i,j$使得$dp[i]+dis(i,j)+dp[j]$最大。
$dis(i,j)$为两点在环上的最长距离。
$dp[i]$表示以$i$为根的子树内以一个端点为根的最长链。
记得考虑顺时针和逆时针两种走法。
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 1000010
using namespace std;
int n,c=1,T=0;
int head[MAXN],degree[MAXN],colour[MAXN],que[MAXN<<1];
long long ans=0,dis[MAXN],dp[MAXN],f[MAXN<<1],g[MAXN<<1];
bool vis[MAXN];
struct Edge{
int next,to,w;
}a[MAXN<<1];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline void add(int u,int v,int w){
a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
a[c].to=u;a[c].w=w;a[c].next=head[v];head[v]=c++;
degree[u]++;degree[v]++;
}
void bfs(int rt){
int l=1,r=1,u,v;
que[1]=rt;
colour[rt]=T;
while(l<=r){
u=que[l];
for(int i=head[u];i;i=a[i].next){
v=a[i].to;
if(!colour[v]){
que[++r]=v;
colour[v]=T;
}
}
l++;
}
}
void topsort(){
int l=1,r=0,u,v;
for(int i=1;i<=n;i++)if(degree[i]==1)que[++r]=i;
while(l<=r){
u=que[l];
for(int i=head[u];i;i=a[i].next){
v=a[i].to;
if(degree[v]>1){
dis[colour[u]]=max(dis[colour[u]],dp[u]+dp[v]+a[i].w);
dp[v]=max(dp[v],dp[u]+a[i].w);
degree[v]--;
if(degree[v]==1)que[++r]=v;
}
}
l++;
}
}
void solve(int rt,int colour){
int u,v,m=0;
u=rt;
for(int i=1;i;){
f[++m]=dp[u];
degree[u]=1;
for(i=head[u];i;i=a[i].next){
v=a[i].to;
if(degree[v]>1){
g[m+1]=g[m]+a[i].w;
u=v;
break;
}
}
}
if(m==2){
int len=0;
for(int i=head[u];i;i=a[i].next)if(a[i].to==rt)len=max(len,a[i].w);
dis[colour]=max(dis[colour],dp[rt]+dp[u]+len);
}
else{
int l=1,r=1;
que[1]=1;
for(int i=head[u];i;i=a[i].next)if(a[i].to==rt){
g[m+1]=g[m]+a[i].w;
break;
}
for(int i=1;i<m;i++){
f[m+i]=f[i];
g[m+i]=g[m+1]+g[i];
}
for(int i=2;i<2*m;i++){
while(l<=r&&i-que[l]>=m)l++;
dis[colour]=max(dis[colour],f[i]+f[que[l]]+g[i]-g[que[l]]);
while(l<=r&&f[que[r]]-g[que[r]]<=f[i]-g[i])r--;
que[++r]=i;
}
}
}
void work(){
for(int i=1;i<=n;i++)if(degree[i]>1&&!vis[colour[i]]){
vis[colour[i]]=true;
solve(i,colour[i]);
ans+=dis[colour[i]];
}
printf("%lld\n",ans);
}
void init(){
int x,w;
n=read();
for(int i=1;i<=n;i++){
x=read();w=read();
add(i,x,w);
}
for(int i=1;i<=n;i++)if(!colour[i]){T++;bfs(i);}
topsort();
}
int main(){
init();
work();
return 0;
}
BZOJ1791: [Ioi2008]Island 岛屿的更多相关文章
- [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
[bzoj1791][ioi2008]Island 岛屿(基环树.树的直径) bzoj luogu 题意可能会很绕 一句话:基环树的直径. 求直径: 对于环上每一个点记录其向它的子树最长路径为$dp_ ...
- bzoj1791: [Ioi2008]Island 岛屿 单调队列优化dp
1791: [Ioi2008]Island 岛屿 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1826 Solved: 405[Submit][S ...
- bzoj千题计划114:bzoj1791: [Ioi2008]Island 岛屿
http://www.lydsy.com/JudgeOnline/problem.php?id=1791 就是求所有基环树的直径之和 加手工栈 #include<cstdio> #incl ...
- BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...
- [BZOJ1791][IOI2008]Island岛屿(环套树DP)
同NOI2013快餐店(NOI出原题?),下面代码由于BZOJ栈空间过小会RE. 大致是对每个连通块找到环,在所有内向树做一遍DP,再在环上做两遍前缀和优化的DP. #include<cstdi ...
- bzoj1791[IOI2008]Island岛屿(基环树+DP)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1791 题目大意:给你一棵n条边的基环树森林,要你求出所有基环树/树的直径之和.n< ...
- BZOJ1791 [Ioi2008]Island 岛屿[基环树+单调队列优化DP]
基环树直径裸题. 首先基环树直径只可能有两种形式:每棵基环树中的环上挂着的树的直径,或者是挂在环上的两个树的最大深度根之间的距离之和. 所以,先对每个连通块跑一遍,把环上的点找出来,然后对环上每个点跑 ...
- 【BZOJ 1791】 [Ioi2008]Island 岛屿
Description 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样 ...
- bzoj 1791: [Ioi2008]Island 岛屿
#include<iostream> #include<cstdio> #define M 1000009 using namespace std; *M],cnt,n,hea ...
随机推荐
- cmd.exe启动参数说明
启动命令解释程序 Cmd.exe 的新范例.如果在不含参数的情况下使用,cmd 将显示操作系统的版本和版权信息. 语法 cmd [{/c | /k}] [/s] [/q] [/d] [{/a | /u ...
- 对checkpoint not completed的理解
如果数据库存在两个日志组log1和log2,首先.-->log1-->log2-->log1,此时(log2切换到log1)触发checkpoint.该checkpoint will ...
- EffectiveJava(8)覆盖equals是要遵守的约定
覆盖equals是要遵守的约定 1.覆盖种类: -类的每个1实例本质上都是唯一的 -不关心类是否提供了"逻辑相等"的测试功能(Random测试是否能随机相同数字) -超类已经覆盖了 ...
- Scrapy的介绍和用法
转载:https://www.toutiao.com/i6493421606306578958/ Scrapy是爬虫必须学会的一个框架!他确实很难搞的透彻!今天就不给大家全部介绍了!还是介绍其中的Cr ...
- IOS 编程中引用第三方的方类库的方法及常见问题
方法一:直接复制全部源文件到项目中 这样的方法就是把第三方类库的全部源文件拷贝到项目中,直接把全部.h和.m文件拖到XCode项目中就可以. 注意: 1. 假设第三方类库引用了一些系统自带类库,那么在 ...
- S3:代理模式 Proxy
为其他对象提供一种代理以控制对这个对象的访问. 使用场合: 1.远程代理:为一个对象在不同的地址空间提供局部代表,隐藏对象存在于不同地址空间的事实.2.虚拟代理:根据需要创建开销很大的对象,通过它来存 ...
- springboot 有用网址收集
http://www.ityouknow.com/spring-boot.html springboot多数据源配置: https://blog.csdn.net/neosmith/article/d ...
- 升级滑动销毁activity,随着手势的滑动而滑动的效果
文章开头先注明本滑动销毁是对 http://blog.csdn.net/xiaanming/article/details/20934541 这篇博客的内容进行一个小小的改动 添加向左滑动打开另外一个 ...
- 【VBA】隐藏正在使用的工作簿
正在使用的工作簿,嫌窗口太多,不利于操作,想把窗口隐藏,该怎么做呢? Public Sub 隐藏正在使用的工作簿() Application.Visible = False MsgBox " ...
- svn上传代码时出现:Authorization failed
出现该问题基本都是三个配置文件的问题,下面把这个文件列出来 svnserve.conf:[general]anon-access = readauth-access = writepassword-d ...