zoj 3820 Building Fire Stations (二分+树的直径)
Building Fire Stations
Time Limit: 5 Seconds
Memory Limit: 131072 KB Special Judge
Marjar University is a beautiful and peaceful place. There are N buildings and
N - 1 bidirectional roads in the campus. These buildings are connected by roads in such a way that there is exactly one path between any two buildings. By coincidence, the length of each road is 1 unit.
To ensure the campus security, Edward, the headmaster of Marjar University, plans to setup two fire stations in two different buildings so that firefighters are able to arrive at the scene of the fire as soon as possible whenever fires occur. That means
the longest distance between a building and its nearest fire station should be as short as possible.
As a clever and diligent student in Marjar University, you are asked to write a program to complete the plan. Please find out two proper buildings to setup the fire stations.
Input
There are multiple test cases. The first line of input contains an integer
T indicating the number of test cases. For each test case:
The first line contains an integer N (2 <= N <= 200000).
For the next N - 1 lines, each line contains two integers Xi and
Yi. That means there is a road connecting building Xi and building
Yi (indexes are 1-based).
Output
For each test case, output three integers. The first one is the minimal longest distance between a building and its nearest fire station. The next two integers are the indexes of the two buildings selected to build the fire stations.
If there are multiple solutions, any one will be acceptable.
Sample Input
2
4
1 2
1 3
1 4
5
1 2
2 3
3 4
4 5
Sample Output
1 1 2
1 2 4
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#define maxn 200005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std; int n,m,ans;
int st,ed,dd,resu,resv;
vector<int>edge[maxn];
int dist[maxn],pre[maxn],city[maxn];
int indst[maxn],inded[maxn];
bool vis[maxn],app[maxn]; int bfs(int sx)
{
int i,j,u,v,res;
queue<int>q;
memset(dist,-1,sizeof(dist));
memset(pre,0,sizeof(pre));
dist[sx]=dd=0;
q.push(sx);
while(!q.empty())
{
u=q.front();
if(dist[u]>=dd)
{
res=u; dd=dist[u];
}
q.pop();
for(i=0;i<edge[u].size();i++)
{
v=edge[u][i];
if(dist[v]==-1)
{
pre[v]=u;
dist[v]=dist[u]+1;
q.push(v);
}
}
}
return res;
}
int bfs1(int sx)
{
int i,j,u,v,res=0;
queue<int>q;
city[sx]=0;
q.push(sx);
while(!q.empty())
{
u=q.front();
res=max(res,city[u]);
q.pop();
for(i=0;i<edge[u].size();i++)
{
v=edge[u][i];
if(!vis[v]&&!app[v])
{
app[v]=1;
city[v]=city[u]+1;
q.push(v);
}
}
}
return res;
}
bool isok(int mid)
{
int i,j,u,v,tu=indst[mid],tv=inded[mid],gap=dist[ed]-2*mid;
//printf("mid:%d tu:%d tv:%d gap:%d\n",mid,tu,tv,gap);
u=tv;
int num=0;
while(u!=tu)
{
if(city[u]+min(num,gap-num)>mid) return false ;
u=pre[u];
num++;
}
return true ;
}
void solve()
{
int i,j,u,v,num=0;
st=bfs(1);
ed=bfs(st);
// printf("st:%d ed:%d\n",st,ed);
memset(vis,0,sizeof(vis));
u=ed;
while(u)
{
inded[num]=u; indst[dist[ed]-num]=u;
num++;
vis[u]=1;
u=pre[u];
}
memset(app,0,sizeof(app));
u=ed;
while(u)
{
city[u]=bfs1(u);
//printf("u:%d city:%d\n",u,city[u]);
u=pre[u];
}
int le=0,ri=dist[ed]/2,mid;
while(le<=ri)
{
mid=(le+ri)>>1;
if(isok(mid))
{
ans=mid; resu=indst[mid]; resv=inded[mid];
if(resu==resv) resu=pre[resu];
ri=mid-1;
}
else le=mid+1;
}
printf("%d %d %d\n",ans,resu,resv);
}
int main()
{
int i,j,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++) edge[i].clear();
int u,v;
for(i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
solve();
}
return 0;
}
1 1 2
1 2 4
zoj 3820 Building Fire Stations (二分+树的直径)的更多相关文章
- ZOJ Problem Set - 3820 Building Fire Stations 【树的直径 + 操作 】
题目:problemId=5374" target="_blank">ZOJ Problem Set - 3820 Building Fire Stations 题 ...
- zoj 3820 Building Fire Stations(二分法+bfs)
题目链接:zoj 3820 Building Fire Stations 题目大意:给定一棵树.选取两个建立加油站,问说全部点距离加油站距离的最大值的最小值是多少,而且随意输出一种建立加油站的方式. ...
- zoj 3820 Building Fire Stations 树的中心
Building Fire Stations Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge ...
- zoj 3820 Building Fire Stations(树上乱搞)
做同步赛的时候想偏了,状态总是时好时坏.这状态去区域赛果断得GG了. 题目大意:给一棵树.让求出树上两个点,使得别的点到两个点较近的点的距离最大值最小. 赛后用O(n)的算法搞了搞,事实上这道题不算难 ...
- ZOJ 3820 Building Fire Stations 求中点+树的直径+BFS
题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小. 意思应该都能明白. 解法:考虑将这棵树摆直如下: 那么我们可以把 ...
- ZOJ 3820:Building Fire Stations(树的直径 Grade C)
题意: n个点的树,边长全为1,求找出两个点,使得树上离这两个点距离最远的那个点,到这两个点(中某个点就行)的距离最小. 思路: 求树直径,找中点,删除中间那条边(如果直径上点数为奇数,则删任何一侧都 ...
- ZOJ 3820 Building Fire Stations
题意: 树上找两个点 使得其它点到这两点随意一点的距离的最大值最小 思路: 最大值最小 想到二分 在二分的基础上判定这个最大值是否可能 怎样判定这个问题就是怎样选那两个点的问题 非常明显 我 ...
- Building Fire Stations ZOJ - 3820 (二分,树的直径)
大意: 给定树, 求两个点, 使得所有其他的点到两点的最短距离的最大值尽量小. 二分答案转为判定选两个点, 向外遍历$x$的距离是否能遍历完整棵树. 取直径两段距离$x$的位置bfs即可. #incl ...
- zoj3820 Building Fire Stations 树的中心
题意:n个点的树,给出n-1条边,每条边长都是1,两个点建立防火站,使得其他点到防火站的最远距离最短. 思路:比赛的时候和队友一开始想是把这两个点拎起来,使得层数最少,有点像是树的中心,于是就猜测是将 ...
随机推荐
- spring boot约定优于配置的这种做法在如今越来越流行了
约定优于配置的这种做法在如今越来越流行了,它的特点是简单.快速.便捷.但是这是建立在程序员熟悉这些约定的前提上.而 Spring 拥有一个庞大的生态体系,刚开始转到 Spring Boot 完全舍弃 ...
- Oracle 学习笔记 14 -- 集合操作和高级子查询
Oracel提供了三种类型的集合操作:各自是并(UNION) .交(INTERSECT). 差(MINUS) UNION :将多个操作的结果合并到一个查询结果中,返回查询结果的并集,自己主动去掉反复的 ...
- hdu2838Cow Sorting(树状数组+逆序数)
题目链接:点击打开链接 题意描写叙述:给定一个长度为100000的数组,每一个元素范围在1~100000,且互不同样,交换当中的随意两个数须要花费的代价为两个数之和. 问怎样交换使数组有序.花费的代价 ...
- 一个人的旅行 HDU杭电2066【dijkstra算法 || SPFA】
pid=2066">http://acm.hdu.edu.cn/showproblem.php? pid=2066 Problem Description 尽管草儿是个路痴(就是在杭电 ...
- JAVA设计模式之【迭代器模式】
迭代器模式 聚合类,聚合对象 电视机遥控器,迭代器,遍历局和对象中的成员 灵活新增遍历方法 将负责遍历数据的方法提取出来,封装到专门的类中,实现数据存储和数据遍历分离.这就是迭代器模式. 灵活性,可扩 ...
- CoreData 从入门到精通(三)关联表的创建
上篇博客中讲了 CoreData 里增删改查的使用,学到这里已经可以应对简单的数据存储需求了.但是当数据模型复杂起来时,例如你的模型类中除了要存储 CoreData 里支持的数据类型外,还有一些自定义 ...
- 如何使用scss/sass
SCSS 与 Sass 异同:http://sass.bootcss.com/docs/scss-for-sass-users/: 欢迎加入前端交流群来py: 转载请标明出处! 废话不多说,直接进入正 ...
- [jzoj 5343] [NOIP2017模拟9.3A组] 健美猫 解题报告 (差分)
题目链接: http://172.16.0.132/senior/#main/show/5343 题目: 题解: 记旋转i次之后的答案为$ans_i$,分别考虑每个元素对ans数组的贡献 若$s_i& ...
- Redis-3-string类型
Redis-3-string类型 标签(空格分隔): redis set key value [ex 秒数] / [px 毫秒数] [nx] /[xx] mset key value key valu ...
- 编程语言与Python学习(一)
1.1 编程与编程语言 1.1.1 编程语言 计算机的发明,是为了用机器解放人力,而编程的目的则是将人类的思想流程按照某种能够被计算机识别的表达方式传递给计算机,从而达到让计算机能够像人脑一样自动执行 ...