题意: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 树的中心的更多相关文章

  1. zoj 3820 Building Fire Stations 树的中心

    Building Fire Stations Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge ...

  2. ZOJ 3820:Building Fire Stations(树的直径 Grade C)

    题意: n个点的树,边长全为1,求找出两个点,使得树上离这两个点距离最远的那个点,到这两个点(中某个点就行)的距离最小. 思路: 求树直径,找中点,删除中间那条边(如果直径上点数为奇数,则删任何一侧都 ...

  3. ZOJ-3820 Building Fire Stations 题解

    题目大意: 一棵树,在其中找两个点,使得其他点到这两个的距离的较小值的最大值的最小值及其方案. 思路: 首先显然一棵树的直径的中点到其他点的距离的最大值必定比其他点的小. 那么感性思考一下就将一棵树的 ...

  4. ZOJ Problem Set - 3820 Building Fire Stations 【树的直径 + 操作 】

    题目:problemId=5374" target="_blank">ZOJ Problem Set - 3820 Building Fire Stations 题 ...

  5. zoj 3820 Building Fire Stations (二分+树的直径)

    Building Fire Stations Time Limit: 5 Seconds      Memory Limit: 131072 KB      Special Judge Marjar ...

  6. zoj 3820 Building Fire Stations(二分法+bfs)

    题目链接:zoj 3820 Building Fire Stations 题目大意:给定一棵树.选取两个建立加油站,问说全部点距离加油站距离的最大值的最小值是多少,而且随意输出一种建立加油站的方式. ...

  7. ZOJ 3820 Building Fire Stations 求中点+树的直径+BFS

    题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小. 意思应该都能明白. 解法:考虑将这棵树摆直如下: 那么我们可以把 ...

  8. Building Fire Stations ZOJ - 3820 (二分,树的直径)

    大意: 给定树, 求两个点, 使得所有其他的点到两点的最短距离的最大值尽量小. 二分答案转为判定选两个点, 向外遍历$x$的距离是否能遍历完整棵树. 取直径两段距离$x$的位置bfs即可. #incl ...

  9. zoj 3820 Building Fire Stations(树上乱搞)

    做同步赛的时候想偏了,状态总是时好时坏.这状态去区域赛果断得GG了. 题目大意:给一棵树.让求出树上两个点,使得别的点到两个点较近的点的距离最大值最小. 赛后用O(n)的算法搞了搞,事实上这道题不算难 ...

随机推荐

  1. LR之Java虚拟用户

    1.认识Java虚拟用户 2.Java虚拟用户的适用范围

  2. IE对toLocaleString小数位处理

    在js中对数值的格式化经常会用到四舍五入.保留小数位数.百分制格式化,分别会用到以下方法 <script type="text/javascript"> var n = ...

  3. PySpark调用自定义jar包

    在开发PySpark程序时通常会需要用到Java的对象,而PySpark本身也是建立在Java API之上,通过Py4j来创建JavaSparkContext. 这里有几点是需要注意的 1. Py4j ...

  4. 关于dom节点绑定滑动事件导致浏览器上下滑动失效解决方案--黄丕巧

    1.移动端开发往往需要添加一下自定义的左右滑动事件,但是添加了左右滑动事件之后就要阻止浏览器大默认事件,否则dom节点的滑动事件和浏览器本身的滑动会出现冲突,导致滑动的时候会出现消失瞬间再出现的效果 ...

  5. Linux入门视频

    为了方便新手学习Linux,本人专门录制了以下Linux初级视频方便学习,本系列多媒体教程已完成的博文: 轻松学习Linux之入门篇 http://chenguang.blog.51cto.com/3 ...

  6. js 控制 table style css

    var table = objj.getElementsByTagName('table'); alert(table[i].width); if(table==null) return; for(v ...

  7. 安装Sass

    最近要开始用 Sass 做一些东西.先来记录一下安装过程. 1.确认本机的 Ruby 版本 2.访问网址下载 Sass 最新版本 https://rubygems.org/gems/sass 3.下载 ...

  8. 第三次作业之Calculator项目随笔

    附:Github的链接:https://github.com/mingyueanyao/object-oriented/tree/master/Calculator 1.初见题目: 第一眼看到题目最大 ...

  9. HDU2948Geometry Darts(简单计算几何)

    题目大意就是说两个人掷飞镖,飞镖在所给定的图形内就记一分,现在给定N个图形(圆.三角形和矩形),问每一次比赛(没人分别掷三次)谁赢. #include <map> #include < ...

  10. How to create custom methods for use in spring security expression language annotations

    From:http://stackoverflow.com/questions/6632982/how-to-create-custom-methods-for-use-in-spring-secur ...