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

此题为寻找基环树上的最长链
又是一道基环树DP,此处处理基环的方式拆开复制一下,然后寻找环上的最长链,此处注意2的时候要特判
关于树上的最长路就直接跑DP就好了
我知道我写的很不详细,但是代码很清楚啊
orz lyd
 #include<cstdio>
#include<iostream>
using namespace std;
const int N=;
struct ee{int to,next,w;}e[N*];
long long head[N],c[N],f[N],du[N],d[N],b[N*],a[N*],q[*N];
int n,timer,cnt;
long long ans;
bool vis[N];
void ins(int u,int v,int w){
e[++cnt].to=v;e[cnt].next=head[u];e[cnt].w=w;head[u]=cnt;du[u]++;
e[++cnt].to=u;e[cnt].next=head[v];e[cnt].w=w;head[v]=cnt;du[v]++;
} void dfs(int now,int k){
c[now]=k;
for (int i=head[now];i;i=e[i].next){
int v=e[i].to;
if(!c[v]) dfs(v,k);
}
} void topsort(){
int l=,r=;
for (int i=;i<=n;i++) if(du[i]==) q[++r]=i;
while(l<r) {
int now=q[++l];
for (int i=head[now];i;i=e[i].next){
int v=e[i].to;
if(du[v]>){
du[v]--;
d[c[now]]=max(d[c[now]],f[now]+f[v]+e[i].w);
f[v]=max(f[v],f[now]+e[i].w);
if(du[v]==)q[++r]=v;
}
}
}
} void dp(int t,int x){
int m=,y=x,i;
do{
a[++m]=f[y];du[y]=;
for(i=head[y];i;i=e[i].next){
int v=e[i].to;
if(du[v]>){
b[m+]=b[m]+e[i].w;
y=e[i].to;
break;
}
}
}while(i);
if(m==){//
int l=;
for (int i=head[y];i;i=e[i].next)
if(e[i].to==x) l=max(l,e[i].w);
d[t]=max(d[t],f[x]+f[y]+l);
return;
}
for(int i=head[y];i;i=e[i].next){
int v=e[i].to;
if(v==x) {
b[m+]=b[m]+e[i].w;
break;
}
}
for (int i=;i<=m;i++){
a[i+m]=a[i];
b[m+i]=b[m+]+b[i];
}
int l,r;
q[l=r=]=;
for (int i=;i<*m;i++){
while(l<=r&&i-q[l]>=m)l++;
d[t]=max(b[i]-b[q[l]]+a[i]+a[q[l]],d[t]);
while(l<=r&&a[q[r]]+b[i]-b[q[r]]<=a[i]) r--;
q[++r]=i;
} } int main(){
scanf("%d",&n);
int v,w;
for (int i=;i<=n;i++){
scanf("%d%d",&v,&w);
ins(i,v,w);
}
for (int i=;i<=n;i++) if (!c[i]) dfs(i,++timer);
topsort();
for (int i=;i<=n;i++){
if(du[i]>&&!vis[c[i]]) {
vis[c[i]]=;
dp(c[i],i);
ans+=d[c[i]];
}
}
cout<<ans<<endl;
}

【BZOJ 1791】 [Ioi2008]Island 岛屿的更多相关文章

  1. bzoj 1791: [Ioi2008]Island 岛屿

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

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

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

  3. bzoj 1791: [Ioi2008]Island 岛屿【基环树+单调队列优化dp】

    我太菜了居然调了一上午-- 这个题就是要求基环树森林的基环树直径和 大概步骤就是找环->dp找每个环点最远能到达距离作为点权->复制一倍环,单调队列dp 找环是可以拓扑的,但是利用性质有更 ...

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

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

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

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

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

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

  7. BZOJ1791: [Ioi2008]Island 岛屿

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

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

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

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

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

随机推荐

  1. [改善Java代码]使用构造块精炼程序

    建议36: 使用构造代码块精炼程序 什么叫代码块(Code Block)?用大括号把多行代码封装在一起,形成一个独立的数据体,实现特定算法的代码集合即为代码块,一般来说代码块是不能单独运行的,必须要有 ...

  2. Windows 7 IE11 F12 不能正常使用

    打开任意网站,按下F12,或者右键鼠标,按L键.出现上面的图的情况!解决办法如下:需要安装下面的补丁(KB3008923) 32位系统:http://www.microsoft.com/en-us/d ...

  3. Ajax发送FormData对象封装的表单数据

    前端页面: <!doctype html> <html lang="en"> <head> <meta charset="UTF ...

  4. Cocos移植到Android-Android.mk编译文件

    我们在上一篇博客中年使用的cocos工具对于C和C++源代码进行编译.事实上cocos工具读取<游戏工程目录>\proj.android\jni\目录中的Android.mk文件,进行交叉 ...

  5. 【知识分享】UIButton setTitle 设置为空 失效

    今天开发练习超级猜图,但是碰到了一个奇怪的问题 困扰我一个晚上,低效的夜晚 可恨~ 示例说明1 [button setTitle:@"" forState:UIControlSta ...

  6. sqlserver 大文件脚本执行

    sqlserver2008中需要执行大文件的脚本,查询分析器中打不开,需要用到sql命令,开始使用osql命令,不过提示对应sqlserver2008中的驱动找不到(具体原因未分析-空闲时在处理),使 ...

  7. Apache使用mysql认证用户

    使用MySQL进行认证 第1步:下载MySQL认证模块,并更名为mod_auth_mysql.so文件,并保存在apache的modules目录下 第2步:apache要加载此功能模块 LoadMod ...

  8. 一个CFile::Remove引起的奇怪问题

    今天收到测试的一个反馈,我们的一个程序,在WIN7.WIN8下安装后,运行不起来,在进程列表中可以看到,但就是不出来窗口,同样的程序在XP下正常,在UAC关闭的情况下也正常,在以管理员权限运行时也正常 ...

  9. iOS 非ARC基本内存管理系列 2-多对象内存管理(2)

    /* 多对象内存管理: 以人拥有车为例涉及到@property底层set方法管理内存的实现 注意:人在换车的时候要进行当前传入的车和人所拥有的车进行判断 */ /******************* ...

  10. 一个功能齐全的IOS音乐播放器应用源码

    该源码是在ios教程网拿过来的,一个不错的IOS音乐播放器应用源码,这个是我当时进公司时 我用了一晚上写的  图片都是在别的地方扒的,主要是歌词同步,及上一曲,下一曲,功能齐全了 ,大家可以学习一下吧 ...