BZOJ3246 [Ioi2013]Dreaming
Description
Serpent(水 蛇)生活的地方有N个水坑,编号为0,...,N - 1,有M条双向小路连接这些水坑。每两个水坑之间至多有一条路径(路径包含一条或多条小路)相互连接,有些水坑之间根本无法互通(即M ≤ N-1 )。Serpent走过每条小路需要一个固定的天数,不同的小路需要的天数可能不同。Serpent的朋友袋鼠希望新修 N - M - 1条小路,让Serpent可以在任何两个水坑间游走。袋鼠可以在任意两个水坑之间修路,Serpent通过每条新路的时间都是L天。袋鼠希望找到一种修 路方式使得修路之后Serpent在每两个水坑之间游走的最长时间最短。
举例说明

上图中有12个水坑8条小路( N = 12, M = 8)。假如L = 2 ,即Serpent通过任何一条新路都需要2天。那么,袋鼠可以修建3条新路:
水坑1和水坑2之间;
水坑1和水坑6之间;
水坑4和水坑10之间。

上图显示了修路后的最终状态。从水坑0走到水坑11的时间最长,需要18天。这是 最佳结果,无论袋鼠如何选择修路方式,总会存在一些水坑对,Serpent需要18天 或者更长时间从其中一个走到另一个。
Input
N : 水坑的数目。
M : 原本存在的小路的数目。
L : Serpent通过新修的路经的时间。
A, B 和 T: 三个包含M个元素的数组,分别表示每条小路的两个端点和通过这条小路的时间。例如,第i条小路连接水坑 A[i-1]和水坑B[i-1],通过这条小路的时间是T[i-1]天。
Output
如上所述,表示游走于两个距离最远的水坑之间所需的时间。
Sample Input
0 8 4
8 2 2
2 7 4
5 11 3
5 1 7
1 3 1
1 9 5
10 6 3
Sample Output
HINT
n <= 500000
正解:树形DP
解题报告:
考场上写的正解,没考虑很多细节,炸到22分。
看了这道题之后感性认识肯定搞出每个连通块内离连通块内所有点中最远距离最小的那个点,有点类似于重心,显然2遍dfs可做。然后就是考虑如何拼接这些连通块。
很容易想到,一定把所有连通块都连在内部距离最大连通块的那个求出来的点上,一定是最优的。但是我们的最远距离计算方式需要谨慎,一般情况下是最大+次大+L,我只考虑了这种就只有22分。事实上最大连通块的直径同样可以成为答案,还有如果L很大的话次大和次次大之间也可构成最长距离,但是注意第三种情况只有是大于等于3个连通块的时候才有可能取到。
//It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
#define RG register
const int MAXN = ;
const int MAXM = ;
const int inf = ;
int n,m,L,ecnt,s;
int first[MAXN],to[MAXM],next[MAXM],w[MAXM];
int f[MAXN][],father[MAXN],son[MAXN],pson[MAXN],belong[MAXN];
int ans1,ans2,ans3,ans; inline int getint()
{
RG int w=,q=; RG char c=getchar();
while((c<'' || c>'') && c!='-') c=getchar(); if(c=='-') q=,c=getchar();
while (c>='' && c<='') w=w*+c-'', c=getchar(); return q ? -w : w;
} inline void dfs(RG int x,RG int fa){
belong[x]=s; RG int now;
for(RG int i=first[x];i;i=next[i]) {
RG int v=to[i]; if(v==fa) continue;
dfs(v,x); now=f[v][]+w[i];
if(now>f[x][]) pson[x]=son[x],f[x][]=f[x][],f[x][]=now,son[x]=v; else if(now>f[x][]) f[x][]=now,pson[x]=v;
}
ans=max(f[x][]+f[x][],ans);
} inline void DFS(RG int x,RG int fa,RG int dis){
if(max(f[x][],dis)<ans) ans=max(f[x][],dis);
for(RG int i=first[x];i;i=next[i]) {
RG int v=to[i]; if(v==fa) continue;
if(v==son[x]) DFS(v,x,max(dis,f[x][])+w[i]);
else DFS(v,x,max(dis,f[x][])+w[i]);
}
} inline void work(){
n=getint(); m=getint(); L=getint(); RG int x,y,z;
for(RG int i=;i<=m;i++) {
x=getint()+; y=getint()+; z=getint();
next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; w[ecnt]=z;
next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; w[ecnt]=z;
}
for(RG int i=;i<=n;i++) if(!belong[i]) s=i,dfs(i,);
if(m==n-) { printf("%d",ans); return ; }
RG int cun=ans;
for(RG int i=;i<=n;i++)
if(belong[i]==i) {
ans=inf,DFS(i,,);
if(ans>ans1) ans3=ans2,ans2=ans1,ans1=ans;
else if(ans>ans2) ans3=ans2,ans2=ans;
else if(ans>ans3) ans3=ans;
}
ans=max(cun,ans1+ans2+L);
if(m<n-) ans=max(ans,ans2+ans3+L*);//必须要多于2块!
printf("%d",ans);
} int main()
{
work();
return ;
}
BZOJ3246 [Ioi2013]Dreaming的更多相关文章
- bzoj 3246 [Ioi2013]Dreaming 贪心
[Ioi2013]Dreaming Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 638 Solved: 241[Submit][Status][Di ...
- 【IOI2013】【Bzoj3246】Dreaming
http://www.lydsy.com/JudgeOnline/problem.php?id=3246 中文题面 天地之初,世界尚在遥远的梦想之中. Serpent(水蛇)生活的地方有N个水坑,编号 ...
- 【bzoj3246】 Ioi2013—Dreaming
www.lydsy.com/JudgeOnline/problem.php?id=3246 (题目链接) 题意 给出一棵不完全的树,要求在树上连最少的边使得所有点联通,并且使得两点间最大距离最小. S ...
- [IOI2013]Dreaming
link 一道非常类似的题目(link) 试题大意 给你一棵含有$n$个节点的有边权森林,问每次连边将会用$L$的代价,问你若此图通过加边成为树时的最小直径.$n \leq 5\times 10^5$ ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 读书笔记:《梦断代码Dreaming in Code》
读书笔记:<梦断代码Dreaming in Code> 拿到<梦断代码>书后,一口气翻了一遍,然后又用了3天时间仔细读了一遍,也不禁掩卷长叹一声,做软件难.虽难,仍要继续走下去 ...
- BZOJ3246 IOI2013Dreaming
如果将森林里每棵树都各自看做一个点,那么最后所连成的树应该是一颗菊花,否则将叶子节点父亲改为根不会更劣. 对于每个点所代表的树,其和根节点相连的点应该是到其他点距离最大值最小的点.这个点显然是直径的中 ...
- BZOJ3249 : [ioi2013]game
线段树套Treap 外层的线段树需要动态开节点 内层Treap需要注意的是,相同y坐标的点不一定是同一个点,所以需要再次离散 空间$O(n\log n)$ 时间$O(n\log^2n)$ #inclu ...
- 《梦断代码Dreaming In Code》阅读笔记(三)
最后这几章感觉上更多是从软件完成整体上来讲的.比如说技术.方法等. 在我看来,其实一个团队一直坚持一种好的.先进的方法是不可少的.如果一个优秀的团队刚愎自用,只随着成员们喜好发展,那不能长久.比如说, ...
随机推荐
- 第51课 C++对象模型分析(下)
1. 单继承对象模型 (1)单一继承 [编程实验]继承对象模型初探 #include <iostream> using namespace std; class Demo { protec ...
- Java AtomicInteger
AtomicInteger,一个提供原子操作的Integer的类.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字.而AtomicIn ...
- 微软职位内部推荐-Software Engineer II
微软近期Open的职位: Job Description Group: Search Technology Center Asia (STCA)/Search Ads Title: SDEII-Sen ...
- [转]在 Eclipse 中嵌入 NASA World Wind Java SDK
使用此开源 SDK 开发 GIS 应用程序 NASA 开发的开源 World Wind Java (WWJ) SDK 为地理信息系统(Geographic Information Systems,GI ...
- scrapy 爬取 useragent
useragentstring.com 网站几乎廊括了所有的User-Agent,刚学了scrapy,打算那它练手,把上面的 user-agent 爬取下来. 本文只爬取常见的 FireFox, Ch ...
- 详解C# 迭代器[转]
迭代器模式是设计模式中行为模式(behavioral pattern)的一个例子,他是一种简化对象间通讯的模式,也是一种非常容易理解和使用的模式.简单来说,迭代器模式使得你能够获取到序列中的所有元素 ...
- Linux实验二报告
北京电子科技学院(BESTI) 实 验 报 告 课程:信息安全系统设计基础 班级: 201352 姓名:池彬宁 贺邦 学号:2013521 ...
- Opencv step by step - 图像载入
之前已经使用过图像载入了,这里再讲述一下其他的一些tip. 先来一次普通的载入: #include <cv.h> #include <highgui.h> int main(i ...
- HoloLens开发手记 - Unity之语音输入
对于HoloLens,语音输入是三大基本输入方式之一,广泛地运用在各种交互中.HoloLens上语音输入有三种形式,分别是: 语音命令 Voice Command 听写 Diction 语法识别 Gr ...
- 阿里客户端工程师试题简析——Android应用的闪退(crash)分析
1. 问题描述 闪退(Crash)是客户端程序在运行时遭遇无法处理的异常或错误时而退出应用程序的表现,请从crash发生的原因分类与解决方法.在出现crash后如何捕捉并分析异常这两个问题给出自己的解 ...