SDOI2011的Dayx第2题

题意:

  在树中找到一条权值和不超过S的链(为什么是链呢,因为题目中提到“使得路径的两端都是城市”,如果不是链那不就不止两端了吗——怎么这么机智的感觉...),使得不在链上的点与这条链的距离最大值最小。

SOL:

  最大值最小!这不是二分的节奏么?然而hzw学长说二分更直观我却一点都没有体会到...

  这道题的关键是猜想(貌似还挺好想)并证明(貌似一直都是可有可无的东西,不过还挺好证的),路径一定在直径上,那么我们先两遍*FS找到直径,用一个队列维护链上的路径,以及预处理出直径上的点其子树中距离最远的点的距离,再维护路径两头距离直径的两端的距离即可,答案即这三者的最大值。

  总感觉应该挺快的吧但是居然比他们二分答案的慢了几倍(A得窝囊),我也就是用了一个set而已(方便取出与删除然而我觉得可以再优化不用这个set...

  关于证明:(自己口胡的证明,极其不严谨

    证明还是非常好证的(也就自己yy),我们假设一条直径,假设最优的链不在这条直径上——我们可以把这条链看作一个点,那么可以证明它的最远点一定是直径的两个端点之一(否则树的直径就可以更长),那么显然这条链是包含直径的一部分的,再证全部包含,只要在部分包含的基础上对延伸进行讨论,就得证了吧...(感觉对了就好了不过是给自己a掉多找一个正当理由...)

CODE:

代码实现不是很难,然而我RE几次方了把DFS改成BFS又把自带queue改成手工队列——结果小细节错误百出...

 /*==========================================================================
# Last modified: 2016-02-12
# Filename: 2016trainning1 t1.cpp
# Description:
==========================================================================*/
#define me AcrossTheSky
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm> #include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#define lowbit(x) (x)&(-x)
#define INF 1000000000
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)
#define ls(a,b) (((a)+(b)) << 1)
#define rs(a,b) (((a)+(b)) >> 1)
#define check(ch) (ch>='0'&&ch<='9')
#define maxn 300001
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int ans=INF;
void read(int &t){
int ch;
for(ch=getchar( );!check(ch);ch=getchar( ));
t=ch-'';
for(ch=getchar( );check(ch);ch=getchar( ))t*=,t+=ch-'';
}
/*==================split line==================*/
int n,s,sume=,maxx;
struct Edge{
int to,len;
}e[maxn*];
struct cmp{
bool operator()(const int &x,const int &y) const{
return x>y;
}
};
int first[maxn],next[maxn*],nextn[maxn],dis[maxn],temp[],f[maxn],pre[maxn];
int q[maxn*];
bool vis[maxn];
set<int,cmp> b;
void addedge(int x,int y,int len){
sume++; e[sume].to=y; e[sume].len=len;
next[sume]=first[x]; first[x]=sume;
}
void bfs(int node,int d){
memset(q,,sizeof(q));
int front=,tail=; dis[node]=;
q[front]=node; vis[node]=true;
while (front<=tail){
int x=q[front];
front++;
if (dis[x]>maxx) maxx=dis[x],temp[d]=x;
for (int i=first[x];i!=-;i=next[i])
if (!vis[e[i].to]){
pre[e[i].to]=x;
dis[e[i].to]=dis[x]+e[i].len;
tail++; q[tail]=e[i].to; vis[e[i].to]=true;
}
}
}
void bfs1(int node,int root){
memset(q,,sizeof(q));
int front=,tail=; q[front]=node;
while (front<=tail){
int x=q[front]; front++; vis[x]=true;
f[root]=max(f[root],dis[x]-dis[root]);
for (int i=first[x];i!=-;i=next[i])
if (e[i].to!=nextn[node] && !vis[e[i].to]){
tail++; q[tail]=e[i].to;
}
}
}
int main(){
read(n); read(s);
FORP(i,,n) first[i]=-;
FORP(i,,n-) {
int x,y,l;
read(x); read(y); read(l);
addedge(x,y,l); addedge(y,x,l);
}
maxx=; bfs(,);
memset(vis,false,sizeof(vis));
maxx=; bfs(temp[],);
int L=temp[],R=temp[];
memset(vis,false,sizeof(vis));
for (int i=L;i!=R;i=pre[i]) nextn[pre[i]]=i;
L=temp[],R=temp[];
for (int i=L;i!=R;i=nextn[i]) { vis[i]=true; bfs1(i,i); }
vis[R]=true; bfs1(R,R);
int llen=,rlen=maxx,head=L,tail=L,len=; while (true){
if (head==R) break;
if (dis[nextn[head]]<s) {
len=dis[nextn[head]];
head=nextn[head];
b.insert(f[head]);
rlen=maxx-dis[head];
continue;
}
break;
} int t=max(rlen,max(llen,*b.begin()));
if (t<ans) ans=t;
while (head!=R){
len=dis[nextn[head]];
head=nextn[head];
rlen=maxx-dis[head];
while(len-dis[tail]>s){
b.erase(f[tail]); tail=nextn[tail]; llen=dis[tail];
}
t=max(rlen,max(llen,*b.begin()));
if (t<ans) ans=t;
}
printf("%d",ans);
}

BZOJ 2282 & 树的直径的更多相关文章

  1. bzoj 2282 [Sdoi2011]消防(树的直径,二分)

    Description 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超越宇宙的热情,所以这个国家 ...

  2. BZOJ 1912: [Apio2010]patrol 巡逻 (树的直径)(详解)

    题目: https://www.lydsy.com/JudgeOnline/problem.php?id=1912 题解: 首先,显然当不加边的时候,遍历一棵树每条边都要经过两次.那么现在考虑k==1 ...

  3. 【BZOJ】1912: [Apio2010]patrol 巡逻(树的直径)

    题目 传送门:QWQ 分析 $ k=1 $ 时显然就是树的直径 $ k=2 $ 时怎么做呢? 做法是把一开始树的直径上的边的边权改成$ -1 $,那么当我们第二次用这些边做环时就抵消了一开始的贡献. ...

  4. 【BZOJ】2657: [Zjoi2012]旅游(journey)(树的直径)

    题目 传送门:QWQ 分析 在任意两个不相邻的点连一条线,求这条线能穿过几个三角形. 建图比较讲究(详见代码) 求树的直径. 代码 #include <bits/stdc++.h> usi ...

  5. bzoj 1776: [Usaco2010 Hol]cowpol 奶牛政坛——树的直径

    农夫约翰的奶牛住在N (2 <= N <= 200,000)片不同的草地上,标号为1到N.恰好有N-1条单位长度的双向道路,用各种各样的方法连接这些草地.而且从每片草地出发都可以抵达其他所 ...

  6. BZOJ 3363 POJ 1985 Cow Marathon 树的直径

    题目大意:给出一棵树.求两点间的最长距离. 思路:裸地树的直径.两次BFS,第一次随便找一个点宽搜.然后用上次宽搜时最远的点在宽搜.得到的最长距离就是树的直径. CODE: #include < ...

  7. D4 树的直径、重心以及基环树

    第一题第二题鉴上我前几篇博客poj1985 poj1849:https://www.cnblogs.com/Tyouchie/p/10384379.html 第三题:数的重心:poj1655 来自sj ...

  8. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

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

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

随机推荐

  1. Awvs如何扫描需要登录的部分

    一个小技巧,可能部分的人习惯了按下一步.所以不大知道.给大家说说哈. 到LOGIN步骤的时候,在Login sequen 新建.然后你懂的了.会新出来一个浏览器,直接登录后一直下一步即可

  2. Resumable Media Uploads in the Google Data Protocol

    Eric Bidelman, Google Apps APIs team February 2010 Introduction The Resumable Protocol Initiating a ...

  3. Repeated DNA Sequences

    All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...

  4. Android 中的selector

    今天做程序时,发现了selector 选择器不单单能用系统的自定义属性(比如,  <item android:state_selected="true" android:co ...

  5. Hadoop入门程序WordCount的执行过程

    首先编写WordCount.java源文件,分别通过map和reduce方法统计文本中每个单词出现的次数,然后按照字母的顺序排列输出, Map过程首先是多个map并行提取多个句子里面的单词然后分别列出 ...

  6. 1.前端笔记之html

    title: 1.前端笔记之HTML date: 2016-04-04 23:21:52 tags: Python categories: Python --- 作者:刘耀 **出处:http://w ...

  7. ThreadGroup分析

    本文为转载:http://sunboyyyl.blog.163.com/blog/static/2247381201211531712330/ 在Java中每一个线程都归属于某个线程组管理的一员,例如 ...

  8. Sublime Text 3 破解+ 汉化包

    破解: 第一步:打开主文件搜索十六进制F7D81AC02005 修改1AC0为B001 第二步:搜索 F3FF8BC7E895 修改其中的8BC7为33C0 第三步:过阻拦未注册提示 搜索 0F859 ...

  9. onItemClick 参数解释

    X, Y两个listview,X里有1,2,3,4这4个item,Y里有a,b,c,d这4个item.如果你点了b这个item.如下:public void onItemClick (AdapterV ...

  10. UML状态图和活动图

    UML状态图和活动图 统一建模语言UML(Unified Modeling Language)是非专利的第三代建模和规约语言.UML是一种开放的方法,用于说明.可视化.构建和编写一个正在开发的.面向对 ...