求树的直径和中心(ZOJ3820)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5374
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
题意:给出n个城市和n-1条道路,要选两个城市作为消防站,问建造在那两个城市可以使距离消防站最远的城市的距离最小?
分析:先求出树的直径,然后在直径中间把边切开,成为两个新的树,分别求出两个新树的重心和直径:
#include"string.h"
#include"stdio.h"
#include"iostream"
#include"algorithm"
#include"queue"
#include"stack"
#include"vector"
#include"stdlib.h"
#include"map"
#include"string"
#include"math.h"
#define M 400009
#define inf 10000000
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int u,v,next;
}edge[M];
int t,head[M];
void init()
{
t=0;
memset(head,-1,sizeof(head));
}
void add(int u,int v)
{
edge[t].u=u;
edge[t].v=v;
edge[t].next=head[u];
head[u]=t++;
}
int dis[M],pre[M],n,use[M],a[M],pref[M],a1[M],a2[M],maxi;
int bfs(int u,int fuck)
{
maxi=0;
int i;
queue<int>q;
for(i=1;i<=n;i++)
use[i]=0;
dis[u]=0;
use[u]=1;
q.push(u);
int ID=u;
while(!q.empty())
{
u=q.front();
q.pop();
for(i=head[u];~i;i=edge[i].next)
{
if(i==(fuck^1)||i==fuck)continue;
int v=edge[i].v;
if(!use[v])
{
use[v]=1;
dis[v]=dis[u]+1;
pre[v]=u;
pref[v]=i;
if(maxi<dis[v])
{
maxi=dis[v];
ID=v;
}
q.push(v);
}
}
}
return ID;
}
void bary()
{
int i;
int u=bfs(1,-2);
pre[u]=-1;
int v=bfs(u,-2);
int cnt=0;
a[++cnt]=v;
for(i=pre[v];i!=-1;i=pre[i])
a[++cnt]=i;
int I=pref[a[cnt/2]]; int u1=bfs(a[cnt/2],I);
pre[u1]=-1;
int v1=bfs(u1,I);
int cnt1=0;
a1[++cnt1]=v1;
for(i=pre[v1];i!=-1;i=pre[i])
a1[++cnt1]=i; int u2=bfs(a[cnt/2+1],I);
pre[u2]=-1;
int v2=bfs(u2,I);
int cnt2=0;
a2[++cnt2]=v2;
for(i=pre[v2];i!=-1;i=pre[i])
a2[++cnt2]=i; printf("%d %d %d\n",max(cnt1/2,cnt2/2),a1[(cnt1+1)/2],a2[(1+cnt2)/2]);
}
int main()
{
int T,i;
cin>>T;
while(T--)
{
scanf("%d",&n);
init();
for(i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
bary();
}
return 0;
}
求树的直径和中心(ZOJ3820)的更多相关文章
- poj2631 求树的直径裸题
题目链接:http://poj.org/problem?id=2631 题意:给出一棵树的两边结点以及权重,就这条路上的最长路. 思路:求实求树的直径. 这里给出树的直径的证明: 主要是利用了反证法: ...
- poj1985 Cow Marathon (求树的直径)
Cow Marathon Time Limit: 2000MS Memory Limit: 30000K Total Submissions: 3195 Accepted: 1596 Case ...
- hdu 4607 Park Visit 求树的直径
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607 题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n) ...
- [USACO2004][poj1985]Cow Marathon(2次bfs求树的直径)
http://poj.org/problem?id=1985 题意:就是给你一颗树,求树的直径(即问哪两点之间的距离最长) 分析: 1.树形dp:只要考虑根节点和子节点的关系就可以了 2.两次bfs: ...
- 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...
- HDU4612+Tarjan缩点+BFS求树的直径
tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...
- hdoj 4612 Warm up【双连通分量求桥&&缩点建新图求树的直径】
Warm up Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Su ...
- 求树的直径+并查集(bfs,dfs都可以)hdu4514
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...
- HDU 4514 - 湫湫系列故事——设计风景线 - [并查集判无向图环][树形DP求树的直径]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 Time Limit: 6000/3000 MS (Java/Others) Memory Li ...
随机推荐
- u方法传参
<a href="{:U('Del/mldel',array('id'=>$vo['id']))}">删除</a>
- tensorflow 单机多GPU mnist实例
http://blog.csdn.net/guotong1988/article/details/74748806 如何使用多GPU http://wiki.jikexueyuan.com/proje ...
- Java并发编程基础
Java并发编程基础 1. 并发 1.1. 什么是并发? 并发是一种能并行运行多个程序或并行运行一个程序中多个部分的能力.如果程序中一个耗时的任务能以异步或并行的方式运行,那么整个程序的吞吐量和可交互 ...
- (转)如何根据RGB值来判断这是种什么颜色?
如何根据RGB值来判断这是种什么颜色? 下面介绍几种典型颜色的RGB值,格式为:颜色(R,G,B). 想象一下有红.绿.蓝三盏射灯打出三束光. 这三束光叠加在一起时产生白色,如果三盏灯的亮度都减半就产 ...
- (转载)UTF-8和GBK的编码方式的部分知识:重要
GBK的文字编码是双字节来表示的,即不论中.英文字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1. 至于UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节) ...
- 基础控制器MVC ,全局判断
public class BaseController : Controller { // // GET: /Base/ protected override voi ...
- Nginx的启动与停止,重启
1.先确定nginx所在的文件位置 如: 重启 1.验证nginx配置文件是否正确 方法一:进入nginx安装目录sbin下,输入命令./nginx -t 2.重启Nginx服务 方法一:进入ngin ...
- RAC:Oracle11gR2:群集的起、停、状态查询
一:查看群集的状态 1.0.1 使用crsctl status resource [-t] 1.0.2 使用crs_stat [-t] 1.0.1 使用srvctl status <obj> ...
- 类似股软(大智慧)之键盘精灵的 vc2008--UNICODE 环境实现
键盘精灵是指,当按下键盘上任意一个数字.字母或符号的时候,都会弹出“键盘精灵”,其类似于股票软件(如大智慧)中的.可以在这里面输入中英文和数字搜索您想要的东西.可以通过输入代码.名称或名称的汉语拼音首 ...
- SQLite学习手册
在实际的应用中,SQLite作为目前最为流行的开源嵌入式关系型数据库,在系统的架构设计中正在扮演着越来越为重要的角色.和很多其它嵌入式NoSQL数据库不同的是,SQLite支持很多关系型数据库的基本特 ...