zoj3820 Building Fire Stations 树的中心
题意:n个点的树,给出n-1条边,每条边长都是1,两个点建立防火站,使得其他点到防火站的最远距离最短。
思路:比赛的时候和队友一开始想是把这两个点拎起来,使得层数最少,有点像是树的中心,于是就猜测是将树的中心找到后,将两棵左右子树分别求树的中心,这两棵树的中心就是答案,but另外一个队友又说了个反例,脑子也不清醒,以为还有没考虑到的,比赛也没A,赛后一想就是最初的猜想,回来之后写了写,报栈了,数据范围太大,真不想改,今天改了改,改成bfs又tle了,囧囧的,把memset和memcpy都改成循环AC了,代码写的很不优雅。
如果最一开始树的直径是偶数,即1-2-3-4,则拆成1-2和3-4。
如果最一开始树的直径是奇数,即1-2-3-4-5,则拆成1-2-3和3-4-5。
丑丑的代码:
/*===============================================================
* Copyright (C) 2014 All rights reserved.
*
* File Name: zoj3172.cpp
* Author:sunshine
* Created Time: 2014年10月14日
*
================================================================*/
#include <map>
#include <queue>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm> using namespace std; #define N 500010 int head[N];
int edgeNum;
struct Edge{
int v,to;
}edge[N];
int edge_u_v[N][]; void addedge(int a,int b){
edge[edgeNum].v = b;
edge[edgeNum].to = head[a];
head[a] = edgeNum ++;
} int vis[N],depth,ind;
int t_vis[N],father[N];
int stack[N];
void bfs(int u){
vis[u] = ;
queue<int>que;
que.push(u);
while(!que.empty()){
int tmp = que.front();
que.pop();
if(vis[tmp] >= depth){
depth = vis[tmp];
ind = tmp;
}
for(int i = head[tmp];i != -;i = edge[i].to){
int v = edge[i].v;
if(vis[v] == ){
vis[v] = vis[tmp] + ;
father[v] = tmp;
que.push(v);
}
}
}
int tmp = ind;
for(int i = ;i < depth;i ++){
stack[i] = tmp;
tmp = father[tmp];
}
return ;
} void init(int n){
edgeNum = ;
//memset(head,-1,sizeof(head));
//memset(vis,0,sizeof(vis));
//memset(father,-1,sizeof(father));
for(int i = ;i <= n;i ++) {
head[i] = -;
vis[i] = ;
father[i] = -;
}
} int main(){
int t;
int n;
int u,v;
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
scanf("%d",&t);
while(t --){
scanf("%d",&n); init(n);
for(int i = ;i < n - ;i ++){
scanf("%d%d",&u,&v);
edge_u_v[i][] = u;
edge_u_v[i][] = v;
addedge(u,v);
addedge(v,u);
} depth = ;
bfs();
for(int i = ;i <= n;i ++) vis[i] = ;
bfs(ind); int ans_one,ans_two;
int depth_one,depth_two;
//left graph
init(n);
u = stack[depth / - ];//chai bian
v = stack[depth / ];
for(int i = ;i < n - ;i ++){
if((edge_u_v[i][] == u && edge_u_v[i][] == v)
|| (edge_u_v[i][] == u && edge_u_v[i][] == v)) ;
else{
addedge(edge_u_v[i][],edge_u_v[i][]);
addedge(edge_u_v[i][],edge_u_v[i][]);
}
} int seperation = stack[depth / ];//the seperation of left and right
int seperation1 = stack[(depth - ) / ];
int long_depth = depth;
depth = ;
bfs(seperation);
for(int i = ;i <= n;i ++) t_vis[i] = vis[i];
for(int i = ;i <= n;i ++) vis[i] = ;
bfs(ind);
ans_one = stack[depth/];//if depth&1 mid else right
depth_one = depth; if(long_depth&){
addedge(u,v);
addedge(v,u);
t_vis[seperation] = ;
}else{
seperation = seperation1;
}
depth = ;
for(int i = ;i <= n;i ++) vis[i] = t_vis[i];
bfs(seperation);
for(int i = ;i <= n;i ++) vis[i] = t_vis[i];
bfs(ind);
if(depth & ) ans_two = stack[depth/];
else ans_two = stack[(depth-)/];
depth_two = depth; if(ans_one == ans_two){
printf("%d %d %d\n",long_depth/,ans_one,(ans_one == )?:);
}else{
printf("%d %d %d\n",max(depth_one/,depth_two/),ans_one,ans_two);
} }
return ;
}
zoj3820 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(树的直径 Grade C)
题意: n个点的树,边长全为1,求找出两个点,使得树上离这两个点距离最远的那个点,到这两个点(中某个点就行)的距离最小. 思路: 求树直径,找中点,删除中间那条边(如果直径上点数为奇数,则删任何一侧都 ...
- 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 (二分+树的直径)
Building Fire Stations Time Limit: 5 Seconds Memory Limit: 131072 KB Special Judge Marjar ...
- zoj 3820 Building Fire Stations(二分法+bfs)
题目链接:zoj 3820 Building Fire Stations 题目大意:给定一棵树.选取两个建立加油站,问说全部点距离加油站距离的最大值的最小值是多少,而且随意输出一种建立加油站的方式. ...
- ZOJ 3820 Building Fire Stations 求中点+树的直径+BFS
题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小. 意思应该都能明白. 解法:考虑将这棵树摆直如下: 那么我们可以把 ...
- Building Fire Stations ZOJ - 3820 (二分,树的直径)
大意: 给定树, 求两个点, 使得所有其他的点到两点的最短距离的最大值尽量小. 二分答案转为判定选两个点, 向外遍历$x$的距离是否能遍历完整棵树. 取直径两段距离$x$的位置bfs即可. #incl ...
- zoj 3820 Building Fire Stations(树上乱搞)
做同步赛的时候想偏了,状态总是时好时坏.这状态去区域赛果断得GG了. 题目大意:给一棵树.让求出树上两个点,使得别的点到两个点较近的点的距离最大值最小. 赛后用O(n)的算法搞了搞,事实上这道题不算难 ...
随机推荐
- no symbol version for module_layout
内核模块编译helloworld: no symbol version for module_layout, 尝试各种解决办法, 都没搞定, 版本也是对的. dmesg提示no symbol vers ...
- fork()函数
现代操作系统提供的三种构造并发程序的方法: •进程 一个进程实体包括:代码段,数据段, 进程控制块 fork()函数:通过系统调用创建一个与原来一模一样的子线程,[用来处理请求信号,而父进程继续一直处 ...
- Bluebird-Collections
Promise实例方法和Promise类核心静态方法用于处理promise或者混合型(mixed)promise和值的集合. 所有的集合实例方法都等效于Promise对象中的静态方法,例如:someP ...
- Thu夏令营 总结
感觉这次thu夏令营简直就是爆RP啊 竟然签了无条件本一 [Waring]RP已空 话说这次考试设定 竟然是下午两点开始考试 考到五点- - 导致中午必须午睡 宾馆里清华也不近 按原本试机安排到12点 ...
- HDU ACM 1325 / POJ 1308 Is It A Tree?
Is It A Tree? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- android学习笔记---发送状态栏通知
发送消息的代码如下: //获取通知管理器 NotificationManager mNotificationManager = (NotificationManager) getSystemServi ...
- Time vs Story Points Estimation [转]
One of the most common questions we get is whether to estimate in time or points. It seems like poin ...
- 第三百四十六天 how can I 坚持
徐斌的电脑来了,thinkpad,感觉还好,电脑也就这样,联想..不好说,不做评论,末日王者吧. 为什么写博客tab键不管用了呢. 下午又去奥体跑了一圈,好累,刚跑完腿疼,现在还好. 还没洗澡呢,都这 ...
- HDU 2101 A + B Problem Too 分类: ACM 2015-06-16 23:57 18人阅读 评论(0) 收藏
A + B Problem Too Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
- CodeForces 534B Covered Path (水题)
题意:给定两个速度,一个一初速度,一个末速度,然后给定 t 秒时间,还每秒速度最多变化多少,让你求最长距离. 析:其实这个题很水的,看一遍就知道怎么做了,很明显就是先从末速度开始算起,然后倒着推. 代 ...