题意:

n个点的树,边长全为1,求找出两个点,使得树上离这两个点距离最远的那个点,到这两个点(中某个点就行)的距离最小。

思路:

求树直径,找中点,删除中间那条边(如果直径上点数为奇数,则删任何一侧都可),分成两个子树,再求中心,即为答案。

代码:

//14:12
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define N 200100 struct Graph{
struct Edge{
int to;
int next;
}e[N*];
int head[N];
int p;
void clear() {
p = ;
memset(head, -, sizeof(head));
}
void addedge(int u, int v) {
e[p].to = v;
e[p].next = head[u];
head[u] = p++;
}
}g; int n;
int dis[N];
int que[N*];
bool vis[N];
int fa[N]; void generateDis(const Graph &g, int s) {
memset(dis, 0x3f, sizeof(dis));
memset(vis, , sizeof(vis));
memset(fa, -, sizeof(fa));
dis[s] = ;
int hd = ;
int tl = ;
que[tl++] = s;
vis[s] = ;
while (hd < tl) {
int now = que[hd++];
vis[now] = ;
for (int i = g.head[now]; i != -; i = g.e[i].next) {
int to = g.e[i].to;
if (dis[to] > dis[now]+) {
dis[to] = dis[now]+;
if (!vis[to]) {
vis[to] = ;
fa[to] = now;
que[tl++] = to;
}
}
}
}
} pair<int, int> getTreeMidPoint(const Graph &g, int s, int &OUT_dis) {
generateDis(g, s);
for (int i = ; i <= n; i++) {
if (dis[i] == 0x3f3f3f3f) dis[i] = -;
}
int u = max_element(&dis[], &dis[]+n) - dis; generateDis(g, u);
for (int i = ; i <= n; i++) {
if (dis[i] == 0x3f3f3f3f) dis[i] = -;
}
int v = max_element(&dis[], &dis[]+n) - dis; //printf("u = %d, v = %d, dis[v] = %d\n", u, v, dis[v]); int now = v;
while (dis[now] > (dis[v]+)/) {
now = fa[now];
} OUT_dis = dis[v]/ + dis[v]%;
return {fa[now], now};
} int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n); g.clear();
for (int i = ; i < n-; i++) {
int a, b;
scanf("%d%d", &a, &b);
g.addedge(a,b);
g.addedge(b,a);
} int tmpdis[];
pair<int ,int> point = getTreeMidPoint(g, , tmpdis[]); //printf("all tree get (%d %d, dis=%d)\n", point.first, point.second, tmpdis[0]); for (int i = g.head[point.first]; i != -; i=g.e[i].next) {
if (g.e[i].to == point.second) g.e[i].to = point.first;
} for (int i = g.head[point.second]; i != -; i=g.e[i].next) {
if (g.e[i].to == point.first) g.e[i].to = point.second;
} pair<int ,int> pa = getTreeMidPoint(g, point.first, tmpdis[]);
pair<int ,int> pb = getTreeMidPoint(g, point.second, tmpdis[]); printf("%d %d %d\n", max(tmpdis[], tmpdis[]), pa.second, pb.second);
}
return ;
}

ZOJ 3820:Building Fire Stations(树的直径 Grade C)的更多相关文章

  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(二分法+bfs)

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

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

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

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

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

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

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

  6. ZOJ 3820 Building Fire Stations

    题意: 树上找两个点  使得其它点到这两点随意一点的距离的最大值最小 思路: 最大值最小  想到二分  在二分的基础上判定这个最大值是否可能 怎样判定这个问题就是怎样选那两个点的问题  非常明显  我 ...

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

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

  8. zoj3820 Building Fire Stations 树的中心

    题意:n个点的树,给出n-1条边,每条边长都是1,两个点建立防火站,使得其他点到防火站的最远距离最短. 思路:比赛的时候和队友一开始想是把这两个点拎起来,使得层数最少,有点像是树的中心,于是就猜测是将 ...

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

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

随机推荐

  1. Y86模拟器的安装

    说白了就几个指令,跟实验楼里面并不完全一样. tar -xvf sim.tar cd sim sudo apt-get install tk sudo ln -s /usr/lib/x86_64-li ...

  2. 微信小程序 | 49,小程序入门集锦系列文章20篇

    以下20篇文章,都是关于微信小程序的文章,以入门常见问题为主.如发现谬误,请与笔者联系. [小程序入门集锦]1,微信小程序在哪里打开 [小程序入门集锦]2,小程序商店 [小程序入门集锦]3,微信小程序 ...

  3. oracle数据库DB_NAME、DBID、DB_UNIQUE_NAME等的区别

    目录 DB_NAME DBID DB_UNIQUE_NAME: INSTANCE_NAME: SID: SERVICE_NAME GLOBAL_DATABASE_NAME: DB_NAME ①是数据库 ...

  4. USACO Section2.3 Longest Prefix 解题报告 【icedream61】

    prefix解题报告------------------------------------------------------------------------------------------ ...

  5. 【LeetCode】Swap Nodes in Pairs(两两交换链表中的节点)

    这是LeetCode里的第24题. 题目要求: 给定一个链表,两两交换其中相邻的节点,并返回交换后的链表. 示例: 给定1->2->3->4, 你应该返回2->1->4- ...

  6. shell之一些测试脚本

    比较文件有无修改,通过修改时间判别 # !/bin/bash dir=$ for file in `ls $dir` do if [ -d $dir/$file ] then echo $file i ...

  7. NYOJ 简单数据结构

    NYOJ 2 括号配对问题 栈的简单应用.可使用STL. #include <iostream> #include <cstdio> #include <cstring& ...

  8. 【bzoj3436】小K的农场 差分约束系统+最长路-Spfa

    原文地址:http://www.cnblogs.com/GXZlegend/p/6801470.html 题目描述 背景 小K是个特么喜欢玩MC的孩纸... 描述 小K在MC里面建立很多很多的农场,总 ...

  9. BZOJ - 2728 与非

    题意: 给定N个数,一个数k和一个范围[L,R].每个数可以使用任意次,k表示与非不超过k位.求出范围内有多少个数可以由他们的与非和表示. 题解: m个数进行NAND,最终的数二进制下某一位如果为1, ...

  10. CS Academy Distinct Neighbours(经典dp)

    CS Academy Distinct Neighbours(经典dp) 题意: 求相邻无相同数字的合法的排列数 题解: 题解 先将相同的数字分为一类,假设共有n组 定义\(dp[i][j]\)表示前 ...