[IOI2013]Dreaming
一道非常类似的题目(link)
试题大意
给你一棵含有$n$个节点的有边权森林,问每次连边将会用$L$的代价,问你若此图通过加边成为树时的最小直径。$n \leq 5\times 10^5$
试题分析
我们可以发现若两棵树要是在合并连接的点一定与树的中心有关。树的中心指对于当$i$为根时,子树上权值和最大的最小。
为什么,应为树的直径的情况只有单独一棵树,两棵树和在一起的,且那时要是合并就是的是树的中心。但其实$CF$那题应该求树的中心也行,因为那是边权都会为$1$.
所以会发现其实应该如果说要把树建完以后会发现是一个菊花树,且根为权重最大的联通块的根。因为若是小的当根的话那么就会多算了一颗树,所以最多只需要算两颗即可。
所以说我们每次处理好中心到叶子节点的最大距离是多少,然后就可以直接去计算答案了。
并且为什么最多只要算到联通块个数$\leq 3$呢,因为刚才说了这是一颗菊花图,所以我们最多有用的其实是两颗子树。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
const int N=;
struct node{
int u,v,w,nex;
}x[N<<];
int cnt,head[N],n,m,l;
void add(int u,int v,int w){
x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++;
}
int dp[N][],dis[N],col,vis[N],son[N];
/*0最长 1 次长*/
void dfs1(int f,int fath){
vis[f]=;
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
dfs1(x[i].v,f);
if(dp[x[i].v][]+x[i].w>=dp[f][]){dp[f][]=dp[f][];dp[f][]=dp[x[i].v][]+x[i].w,son[f]=x[i].v;}
else if(dp[x[i].v][]+x[i].w>dp[f][]){dp[f][]=dp[x[i].v][]+x[i].w;}
}
return;
}
int ans,k;
void dfs2(int f,int fath,int Dis){
if(Dis>dp[f][]){
dp[f][]=dp[f][];dp[f][]=Dis;son[f]=fath;
}
else if(Dis>dp[f][]){dp[f][]=Dis;}
ans=max(ans,dp[f][]);k=min(k,dp[f][]);
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
if(son[f]==x[i].v) dfs2(x[i].v,f,dp[f][]+x[i].w);
else dfs2(x[i].v,f,dp[f][]+x[i].w);
}
}
int calc[N];
signed main(){
memset(head,-,sizeof(head));
n=read(),m=read(),l=read();
for(int i=;i<=m;i++){
int u=read()+,v=read()+,w=read();
add(u,v,w),add(v,u,w);
}
for(int i=;i<=n;i++){
if(!vis[i]){
dfs1(i,);
k=INT_MAX;
dfs2(i,,);
calc[++col]=k;
}
}
sort(calc+,calc+col+);
if(col>=) ans=max(ans,calc[col]+calc[col-]+l);
if(col>=) ans=max(ans,calc[col-]+calc[col-]+*l);
printf("%d",ans);
}
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
using namespace std;
inline int read(){
int f=,ans=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){ans=ans*+c-'';c=getchar();}
return f*ans;
}
const int N=;
struct node{
int u,v,w,nex;
}x[N<<];
int cnt,head[N],n,m,l;
void add(int u,int v,int w){
x[cnt].u=u,x[cnt].v=v,x[cnt].w=w,x[cnt].nex=head[u],head[u]=cnt++;
}
int dp[N][],dis[N],col,vis[N],son[N];
/*0最长 1 次长*/
void dfs1(int f,int fath){
vis[f]=;
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
dfs1(x[i].v,f);
if(dp[x[i].v][]+x[i].w>=dp[f][]){dp[f][]=dp[f][];dp[f][]=dp[x[i].v][]+x[i].w,son[f]=x[i].v;}
else if(dp[x[i].v][]+x[i].w>dp[f][]){dp[f][]=dp[x[i].v][]+x[i].w;}
}
return;
}
int ans,k,pos;
struct Node{
int pos,calc;
}S[N<<];
void dfs2(int f,int fath,int Dis){
if(Dis>dp[f][]){
dp[f][]=dp[f][];dp[f][]=Dis;son[f]=fath;
}
else if(Dis>dp[f][]){dp[f][]=Dis;}
ans=max(ans,dp[f][]);k=min(k,dp[f][]);
if(dp[f][]==k) pos=f;
for(int i=head[f];i!=-;i=x[i].nex){
if(x[i].v==fath) continue;
if(son[f]==x[i].v) dfs2(x[i].v,f,dp[f][]+x[i].w);
else dfs2(x[i].v,f,dp[f][]+x[i].w);
}
}
bool cmp(Node x1,Node x2){return x1.calc<x2.calc;}
signed main(){
memset(head,-,sizeof(head));
n=read(),m=read(),l=;
for(int i=;i<=m;i++){
int u=read(),v=read(),w=;
add(u,v,w),add(v,u,w);
}
for(int i=;i<=n;i++){
if(!vis[i]){
dfs1(i,);
k=INT_MAX;
dfs2(i,,);
S[++col].calc=k;
S[col].pos=pos;
}
}
sort(S+,S+col+,cmp);
if(col>=) ans=max(ans,S[col].calc+S[col-].calc+l);
if(col>=) ans=max(ans,S[col-].calc+S[col-].calc+*l);
printf("%d\n",ans);
for(int i=col-;i>=;i--) cout<<S[col].pos<<" "<<S[i].pos<<endl;
}
CF
[IOI2013]Dreaming的更多相关文章
- bzoj 3246 [Ioi2013]Dreaming 贪心
[Ioi2013]Dreaming Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 638 Solved: 241[Submit][Status][Di ...
- 【bzoj3246】 Ioi2013—Dreaming
www.lydsy.com/JudgeOnline/problem.php?id=3246 (题目链接) 题意 给出一棵不完全的树,要求在树上连最少的边使得所有点联通,并且使得两点间最大距离最小. S ...
- BZOJ3246 [Ioi2013]Dreaming
Description Serpent(水 蛇)生活的地方有N个水坑,编号为0,...,N - 1,有M条双向小路连接这些水坑.每两个水坑之间至多有一条路径(路径包含一条或多条小路)相互连接,有些水坑 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 【IOI2013】【Bzoj3246】Dreaming
http://www.lydsy.com/JudgeOnline/problem.php?id=3246 中文题面 天地之初,世界尚在遥远的梦想之中. Serpent(水蛇)生活的地方有N个水坑,编号 ...
- 读书笔记:《梦断代码Dreaming in Code》
读书笔记:<梦断代码Dreaming in Code> 拿到<梦断代码>书后,一口气翻了一遍,然后又用了3天时间仔细读了一遍,也不禁掩卷长叹一声,做软件难.虽难,仍要继续走下去 ...
- BZOJ3249 : [ioi2013]game
线段树套Treap 外层的线段树需要动态开节点 内层Treap需要注意的是,相同y坐标的点不一定是同一个点,所以需要再次离散 空间$O(n\log n)$ 时间$O(n\log^2n)$ #inclu ...
- 《梦断代码Dreaming In Code》阅读笔记(三)
最后这几章感觉上更多是从软件完成整体上来讲的.比如说技术.方法等. 在我看来,其实一个团队一直坚持一种好的.先进的方法是不可少的.如果一个优秀的团队刚愎自用,只随着成员们喜好发展,那不能长久.比如说, ...
- 《梦断代码Dreaming In Code》阅读笔记(二)
这段时间一口气读了5章,所以想着现在一块写阅读笔记. 在阅读的这段时间,我一直是晚上进行阅读,很多时候都是读完一看已经一个小时了,效果还不错.闲话不表,说说阅读心得. 关于底层语言或是低级语言,我之前 ...
随机推荐
- Linux中新增硬盘的分区,格式化与挂载
Linux中新增硬盘的分区,格式化与挂载 本篇教程内容为怎样对Linux新增硬盘进行挂载,所以如果有准备新增硬盘但是有各种问题的,请参看本篇教程. 我们先说说什么是挂载? 我们知道Linux中的所有设 ...
- 3星|麦肯锡合伙人《从1到N》:PPT讲稿,图表不错,讲解不够深入
从1到N:企业数字化生存指南 两位作者是麦肯锡合伙人.全书插图比较多,图做的还比较有水平.但是相关文字不够深入,我读后的感觉是:图表不是两位执笔者做的,他们对细节不清楚,对图表涉及到的行业也缺乏深入的 ...
- mui搜索框 搜索点击事件
<div class="mui-input-row mui-search"> <input type="search" class=" ...
- v-on 事件修饰符
事件修饰符: .stop 阻止冒泡 .prevent 阻止默认事件 .capture 添加事件侦听器时使用事件捕获模式 .self 只当该事件在该元素本身时(不是子元素)触发时才回调 .once ...
- 【第二章】MySQL数据库基于Centos7.3-部署
一.MySQL数据库的官方网址: https://www.mysql.com/ https://www.oracle.com/ http://dev.mysql.com/doc/refman/5.7/ ...
- linux云主机小技巧
微信服务器安装 安装库 python 3.5环境下 pip安装web.py时 会报错 "no module named "utils" 等问题 更换命令为“pip ins ...
- 基于spec探路者团队贪吃蛇作品的评论
1 运动功能 由以上两图贪吃蛇的位置不同可知,运动功能实现.并且我能够通过使用键盘上的上下左右方位键控制蛇的移动方向,蛇在控制的方向上进行直线前进. 2 吃食物功能 以上两图可知吃食物功能实现.当界面 ...
- SSH新学,关于面向对象的看法
流程:model-->dao-->service-->impService-->action 如果只是操作单个的一个表,比如user表,则都写到user的流程中 如果要操作俩个 ...
- 配置resin web方式部署项目
写在前面,推荐下载resin4.0.47版本.其它版本没有测试 最近打算做一个小项目,然后容器选用了resin.想通过web提交war文件的方式 进行部署,更新代码也方便. 试了resin最新的版本( ...
- 按照事务类型分析 DB2 事物的性能
概述 事务是数据库系统中的核心概念之一.作为数据库系统的逻辑工作单元(Unit of Work),事务必须具有四个属性,即原子性.一致性.隔离性和持久性(ACID).数据库系统往往通过锁机制保证事务的 ...