[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的10个最危险的命令
Linux命令行佷有用.很高效,也很有趣,但有时候也很危险,尤其是在你不确定你自己在正在做什么时候. 这篇文章将会向你介绍十条命令,但你最好不要尝试着去使用. 当然,以下命令通常都是在root权限下才 ...
- Charles的安装与破解
Charles启动需要安装java环境,不知配置了jdk就可以,而是需要java环境,否则下载后点击启动会提示找不到suitable java 1 安装java环境 安装java环境是在https:/ ...
- win7下配置spark
1.安装jdk(配置JAVA_HOME,CLASSPATH,path) 2.安装scala(配置SCALA_HOME,path) 3.安装spark Spark的安装非常简单,直接去Download ...
- 套接口socket编程(Client/Server编程实例)
基本概念 套接口也就是网络中的ID.网络通信,归根到底还是进程间通信(不同计算机上的进程间的通信).在网络中,每一个节点(计算机或路由器)都有一个网络地址,也就是IP地址. IP地址:在网络中唯一标识 ...
- kettle_Spoon 修改共享DB连接带汉字引发的错误
win10下: kettle_Spoon 修改共享DB连接带汉字引发的错误: Unexpected problem reading shared objects from XML file : nul ...
- Python Pygame (4) 图像的变换
Pygame中的transform模块可以使得你能够对图像(也就是Surface对象)做各种动作,列如左右上下翻转,按角度转动,放大缩小......,并返回Surface对象.这里列举了transfo ...
- 软工实践-Alpha 冲刺 (4/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 很胖,刚学,照猫画虎做了登录与注册界面. 展示GitHub ...
- 给个理由走下去——读《我是一只IT小小鸟》有感
和很多人一样,高考失利,迷迷茫茫的走进了软件学院.关于这个专业,具体学什么是一概不知,只知道学软件的很帅很帅,幻想着以后当个行侠仗义的黑客,或是开发一款自己的游戏都是十分诱惑人的.然而这个世界有个不成 ...
- weblogic下JNDI及JDBC连接测试(weblogic环境)
JNDI的专业解释,大家自行去网络搜索吧,这里就不啰嗦了. 单纯从使用角度看,可以简称把它看成一个key-value的“哈希资源”容器.给定一个string类型的key,可以把任何类型的value,放 ...
- Spring注解原理
一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解 ...