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)的算法搞了搞,事实上这道题不算难 ...
随机推荐
- 【LR】安装LR11后遇到的问题
(1)问题:录制脚本时无法弹出IE浏览器 解决方法: 正确的是C:\Program Files (x86)\Internet Explorer\iexplore.exe 错误是:C:\Program ...
- JavaScript 教程学习进度备忘
书签:"JavaScript 课外书"即“JS 教程”底部的“马上开始学习 JavaScript 高级教程吧 !”链接跳过,它属于高级教程:另外跳过的内容有待跟进 ________ ...
- 【LeetCode】100 - Same Tree
Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...
- Linux securecrt破解
其实,以前接触过破解的东西,但是很多东西早就忘记了,何况是在Linux环境下. 结果我常识更改时间,哦,不是更改日期,往后推4天,结果显示了26 days remaining. 所以完全可以更改日期来 ...
- JavaEE5 Tutorial_Jsp,EL
Jsp的各种元素在转化为servlet时处理是不一样的:指令,控制web容器如何处理页面脚本,被插入到生成的servlet里EL表达式,作为参数传递到解析器get/set Property,变成方 ...
- pybombs 安装
参考:https://github.com/gnuradio/pybombs 先装:pip 然后: pip install PyBOMBS 更新源: pybombs recipes add gr-re ...
- js 剪切板应用clipboardData
http://blog.csdn.net/fox123871/article/details/6454634 <a href="http://blog.csdn.net/fox1238 ...
- 如何注册AWS Global账号
去年底AWS宣布落地中国以来,可能很多童鞋都在热切地等待试用AWS中国的服务.但是AWS中国目前还在犹抱琵琶半遮面,没有完全向大家开放.不过,大家也不必干等待.要是真感兴趣的话可以自己或者让公司先注册 ...
- Masonry 实现输入框随键盘位置改变
Github: https://github.com/saitjr/MasonryDemo 直接上代码: #import "ViewController4.h" #import & ...
- SQL Server 索引 之 书签查找 <第十一篇>
一.书签查找的概念 书签可以帮助SQL Server快速从非聚集索引条目导向到对应的行,其实这东西几句话我就能说明白. 如果表有聚集索引(区段结构),那么书签就是从非聚集索引找到聚集索引后,利用聚集索 ...