题意: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. 【转】linux mknod命令解析

    转自:http://www.cnblogs.com/cobbliu/archive/2011/07/05/2389014.html 个人觉得linux的软件设计思想异常强大,比如把所有的设备都当做文件 ...

  2. 深入解读saltstack的安装及配置1

    安装 一.安装方法:http://www.linuxeye.com/Linux/2765.html 二.建议安装epel后安装saltstack:http://www.a8z8.com/html/20 ...

  3. springMVC框架访问web-inf下的jsp文件

    博客原文章:http://td.xue163.com/1042/1/10425265.html 用户提出问题:springMVC框架访问web-inf下的jsp文件,具体如下: 使用springMVC ...

  4. mybatis源码学习: 编译的方法

    mybatis3用了一段时间,抽出时间来研究一下.具体用法参考官方文档就行,源码在这里.mybatis相对而言,规模较小,可以从中学习如何编写高质量的java项目. mybatis3使用maven管理 ...

  5. 一个Web页面的生命周期 ,面试常常被问到

    常规页生命周期阶段 一般来说,页要经历下表概述的各个阶段.除了页生命周期阶段以外,在请求前后还存在应用程序阶段,但是这些阶段并不特定于页.有关更多信息,请参见 ASP.NET 应用程序生命周期概述. ...

  6. 实例化spring容器

    方法一:在类路径下寻找配置来实例化容器 ApplicationContext ctx = new String[]{"beans.xml"}); 方法二:在文件系统路径下寻找配置文 ...

  7. SpringMVC + Spring + MyBatis 学习笔记:提交数据遭遇基础类型和日期类型报400错误解决方法

    系统:WIN8.1 数据库:Oracle 11GR2 开发工具:MyEclipse 8.6 框架:Spring3.2.9.SpringMVC3.2.9.MyBatis3.2.8 使用SpringMVC ...

  8. Web服务器与Servlet容器

    今日要闻: Oracle启动了JRE7到JRE8的自动更新, JRE8发布于2014.3,于2014.10成为java.com默认版本, JRE7发布于2011.7, Oracle指定的Java生命政 ...

  9. gVIM 简洁配置 in Windows

    原文链接:http://www.errdev.com/post/2/ 捣鼓了一段时间的VIM,神器终归是神器,果然编码效率提升了许多,当然还需要很多插件来配合.自己装插件很麻烦,还要有Vundle这个 ...

  10. openstack kilo 流量