ZOJ 3820:Building Fire Stations(树的直径 Grade C)
题意:
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)的更多相关文章
- 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(二分法+bfs)
题目链接:zoj 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(树上乱搞)
做同步赛的时候想偏了,状态总是时好时坏.这状态去区域赛果断得GG了. 题目大意:给一棵树.让求出树上两个点,使得别的点到两个点较近的点的距离最大值最小. 赛后用O(n)的算法搞了搞,事实上这道题不算难 ...
- ZOJ 3820 Building Fire Stations 求中点+树的直径+BFS
题意:给一棵树,要求找出两个点,使得所有点到这两个点中距离与自己较近的一个点的距离的最大值(所有点的结果取最大的值,即最远距离)最小. 意思应该都能明白. 解法:考虑将这棵树摆直如下: 那么我们可以把 ...
- ZOJ 3820 Building Fire Stations
题意: 树上找两个点 使得其它点到这两点随意一点的距离的最大值最小 思路: 最大值最小 想到二分 在二分的基础上判定这个最大值是否可能 怎样判定这个问题就是怎样选那两个点的问题 非常明显 我 ...
- ZOJ Problem Set - 3820 Building Fire Stations 【树的直径 + 操作 】
题目:problemId=5374" target="_blank">ZOJ Problem Set - 3820 Building Fire Stations 题 ...
- zoj3820 Building Fire Stations 树的中心
题意:n个点的树,给出n-1条边,每条边长都是1,两个点建立防火站,使得其他点到防火站的最远距离最短. 思路:比赛的时候和队友一开始想是把这两个点拎起来,使得层数最少,有点像是树的中心,于是就猜测是将 ...
- Building Fire Stations ZOJ - 3820 (二分,树的直径)
大意: 给定树, 求两个点, 使得所有其他的点到两点的最短距离的最大值尽量小. 二分答案转为判定选两个点, 向外遍历$x$的距离是否能遍历完整棵树. 取直径两段距离$x$的位置bfs即可. #incl ...
随机推荐
- 6 Django的视图层
视图函数 一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . ...
- 2,MongoDB之增删改查及pymongo的使用
本章我们来学习一下关于 MongoDB的增删改查 一.MongoDB操作 之 原生ORM,根本不存在SQL语句 创建数据库:这里和一般的关系型数据库一样,都要先建立一个自己的数据库空间 是的,Mong ...
- java程序——输入判断成绩
import java.util.*; class ExceptionOut extends Exception{ } public class Score { public static void ...
- 《Cracking the Coding Interview》——第18章:难题——题目9
2014-04-29 04:18 题目:有一连串的数被读入,设计一个数据结构,能随时返回当前所有数的中位数. 解法:用一个大顶堆,一个小顶堆将数分成数量最接近的两份,就能轻松得到中位数了. 代码: / ...
- 用gulp清除、移动、压缩、合并、替换代码
之前前端代码部署时用的是grunt,后来又出了个gulp工具,最近试用了一下,很方便,感觉比grunt简单好用,下面把一些常见的任务列一下,备用. var gulp = require('gulp') ...
- 每天一个Linux命令(1):cd命令
cd命令用来切换工作目录至dirName,其中dirName表示绝对路径或相对路径.若目录名称省略,则切换至使用者的home directory(也就是钢login时所在的目录).另外,~ 也表示ho ...
- Python 3基础教程16-类
本文介绍类和简单使用,类是需要class这个关键字来声明的,一般如下面的语法: class className: def fun1(): pass def fun2(): pass 看下面demo.p ...
- 孤荷凌寒自学python第二十天python的匿名函数与偏函数
孤荷凌寒自学python第二十天python的匿名函数与偏函数 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Python为使函数的使用更加方便高效,可以使用两种特殊的函数简化语句书写. 一 ...
- RelativeLayout布局属性
Android RelativeLayout属性 // 相对于给定ID控件 android:layout_above 将该控件的底部置于给定ID的控件之上; android:layout_below ...
- django的聚合函数和aggregate、annotate方法使用
支持聚合函数的方法: 提到聚合函数,首先我们要知道的就是这些聚合函数是不能在django中单独使用的,要想在django中使用这些聚合函数,就必须把这些聚合函数放到支持他们的方法内去执行.支持聚合函数 ...