题意:

给你一颗树,让你放两个点,放在哪里的时候任意点到某个最近的消防站最远值最小。

思路:

树的直径类题目。

首先我们想两个点会把整棵树分成两个团,所以肯定会在树的某个链上切开。

而且要切一定切在树的直径上,如果不切在直径上,那有一个团的最场距离不就是(直径长度lenth/2了吗)。

所以我们取出直径,枚举切在哪里。

左右两半边的计算方法是一样的,如下图:

我们先算出直径上每个节点的最长距离,因为对于某一个节点,它的分支的长度它到不会超过到直径两端的长度,这样我们就很好算了。

跑两遍:第一次从左到右对左半边的团的直径前缀记录下来,第二次从右到左对右半边的直径后缀记录下来

(注意:1. 对lenth取max,2. 如果直径是偶数如:8,lenth要记为5,mid+1)

最后再跑一遍记录答案就行了。

 #define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#include <cstdio>//sprintf islower isupper
#include <cstdlib>//malloc exit strcat itoa system("cls")
#include <iostream>//pair
#include <fstream>//freopen("C:\\Users\\13606\\Desktop\\草稿.txt","r",stdin);
#include <bitset>
//#include <map>
//#include<unordered_map>
#include <vector>
#include <stack>
#include <set>
#include <string.h>//strstr substr
#include <string>
#include <time.h>//srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9;
#include <cmath>
#include <deque>
#include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
#include <vector>//emplace_back
//#include <math.h>
//#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor
#include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare)
using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
#define fo(a,b,c) for(register int a=b;a<=c;++a)
#define fr(a,b,c) for(register int a=b;a>=c;--a)
#define mem(a,b) memset(a,b,sizeof(a))
#define pr printf
#define sc scanf
#define ls rt<<1
#define rs rt<<1|1
typedef long long ll;
void swapp(int &a,int &b);
double fabss(double a);
int maxx(int a,int b);
int minn(int a,int b);
int Del_bit_1(int n);
int lowbit(int n);
int abss(int a);
//const long long INF=(1LL<<60);
const double E=2.718281828;
const double PI=acos(-1.0);
const int inf=(<<);
const double ESP=1e-;
const int mod=(int)1e9+;
const int N=(int)1e6+; int n; bool vis[N];
vector<vector<int> >G(N);
struct node{int now,val;};
void Init()
{
for(int i=;i<=n;++i)
vis[i]=;
}
int Val_bfs(node start)
{
int ans=;
queue<node>q;
q.push(start);
while(!q.empty())
{
node v=q.front();q.pop();
ans=max(ans,v.val);
vis[v.now]=;
int sz=G[v.now].size();
for(int i=;i<sz;++i)
{
int to=G[v.now][i];
if(!vis[to])
q.push({to,v.val+});
}
}
return ans;
} int Start,End;
void queue_dfs1(node start)
{
Init();
int max_=;
queue<node>q;
q.push(start);
while(!q.empty())
{
node v=q.front();q.pop();
vis[v.now]=;
if(max_<v.val)max_=v.val,Start=v.now;
int sz=G[v.now].size();
for(int i=;i<sz;++i)
{
int to=G[v.now][i];
if(!vis[to])
q.push({to,v.val+});
}
}
}
int fa[N];
void queue_dfs2()
{
for(int i=;i<=n;++i)fa[i]=;
Init();
int max_=;
queue<node>q;
q.push({Start,});
while(!q.empty())
{
node v=q.front();q.pop();
vis[v.now]=;
if(max_<v.val)max_=v.val,End=v.now;
int sz=G[v.now].size();
for(int i=;i<sz;++i)
{
int to=G[v.now][i];
if(!vis[to])
q.push({to,v.val+}),fa[to]=v.now;
}
}
}
int Line[N];
int get_line()
{
Init();
int pos=End;
int cnt=;
while(fa[pos])
Line[++cnt]=pos,vis[Line[cnt]]=,pos=fa[pos];
Line[++cnt]=pos,vis[Line[cnt]]=;
return cnt;
}
int Val[N];
struct mark
{
int L,p1;
}memery[N],memery2[N];
void solve(int cnt)
{
int p1;
for(int i=;i<=cnt;++i)
Val[i]=Val_bfs({Line[i],});
memery[]=memery2[cnt+]={-,-};
for(int i=;i<=cnt-;++i)
{
int lenth=(Val[i]+i+)/;
if((Val[i]+i)%==)
lenth++;
p1=Line[lenth];
if(lenth<memery[i-].L)
memery[i]=memery[i-];
else
memery[i]={lenth,p1};
}
int p2;
for(int i=cnt;i>=;--i)
{
int lenth=(Val[i]+cnt+-i+)/;
if((Val[i]+cnt+-i)%==)
lenth++;
p2=Line[cnt+-lenth];
if(lenth<memery2[i+].L)
memery2[i]=memery2[i+];
else
memery2[i]={lenth,p2};
}
int L=inf,P1,P2;
for(int i=;i<=cnt-;++i)
{
if(L>max(memery[i].L,memery2[i+].L))
L=max(memery[i].L,memery2[i+].L),P1=memery[i].p1,P2=memery2[i+].p1;
}
pr("%d %d %d\n",L-,P1,P2);
} int main()
{
// freopen("C:\\Users\\13606\\Desktop\\草稿.txt","r",stdin);
int T;
sc("%d",&T);
while(T--)
{
sc("%d",&n);
for(int i=;i<=n;++i)
G[i].clear();
for(int i=;i<=n-;++i)
{
int u,v;
sc("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
queue_dfs1({,});
queue_dfs2();
int lenth=get_line();
solve(lenth);
}
return ;
} /**************************************************************************************/ int maxx(int a,int b)
{
return a>b?a:b;
} void swapp(int &a,int &b)
{
a^=b^=a^=b;
} int lowbit(int n)
{
return n&(-n);
} int Del_bit_1(int n)
{
return n&(n-);
} int abss(int a)
{
return a>?a:-a;
} double fabss(double a)
{
return a>?a:-a;
} int minn(int a,int b)
{
return a<b?a:b;
}

树上选两点(使最短)树的直径+bfs的更多相关文章

  1. Codeforces 1182D Complete Mirror 树的重心乱搞 / 树的直径 / 拓扑排序

    题意:给你一颗树,问这颗树是否存在一个根,使得对于任意两点,如果它们到根的距离相同,那么它们的度必须相等. 思路1:树的重心乱搞 根据样例发现,树的重心可能是答案,所以我们可以先判断一下树的重心可不可 ...

  2. poj2631 树的直径 + bfs

    //Accepted 492 KB 0 ms //树的直径 bfs #include <cstdio> #include <cstring> #include <iost ...

  3. 从Trie树(字典树)谈到后缀树

    转:http://blog.csdn.net/v_july_v/article/details/6897097 引言 常关注本blog的读者朋友想必看过此篇文章:从B树.B+树.B*树谈到R 树,这次 ...

  4. java实现哈弗曼树和哈夫曼树压缩

    本篇博文将介绍什么是哈夫曼树,并且如何在java语言中构建一棵哈夫曼树,怎么利用哈夫曼树实现对文件的压缩和解压.首先,先来了解下什么哈夫曼树. 一.哈夫曼树 哈夫曼树属于二叉树,即树的结点最多拥有2个 ...

  5. 树&二叉树&哈夫曼树

    1.树 需要注意的两点:n(n>=0)表示结点的个数,m表示子树的个数 (1)n>0时,树的根节点是唯一的. (2)m>0时,子树的个数没有限制. 结点的度和树的度 (1)结点的度是 ...

  6. [算法]从Trie树(字典树)谈到后缀树

    我是好文章的搬运工,原文来自博客园,博主July_,地址:http://www.cnblogs.com/v-July-v/archive/2011/10/22/2316412.html 从Trie树( ...

  7. BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...

  8. [转]B树(多向平衡查找树)详解

    B-树是对2-3树数据结构的扩展.它支持对保存在磁盘或者网络上的符号表进行外部查找,这些文件可能比我们以前考虑的输入要大的多(以前的输入能够保存在内存中). (B树和B+树是实现数据库的数据结构,一般 ...

  9. 树-二叉搜索树-AVL树

    树-二叉搜索树-AVL树 树 树的基本概念 节点的度:节点的儿子数 树的度:Max{节点的度} 节点的高度:节点到各叶节点的最大路径长度 树的高度:根节点的高度 节点的深度(层数):根节点到该节点的路 ...

随机推荐

  1. vue整合adminLTE

    前端框架AdminLTE 中文教程 如何用vue整合adminlte模板 1.adminlte 下载地址 : https://github.com/almasaeed2010/AdminLTE/rel ...

  2. jQuery属性操作之值操作

    值操作是对DOM属性value进行读取和设置操作. 比如html(). text(). val(). 1. html 1. 1 html()获取值 返回值:String 描述:获取集合中第一个匹配元素 ...

  3. IDEA如何将写好的java类(UDF函数)打成jar包上传linux

    一.编写一个UDF函数,实现将字符串大写转小写 import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; ...

  4. C++入门经典-例7.6-this指针,同一个类的不同对象数据

    1:对于类的非静态成员,每个对象都有自己的一份拷贝,即每个对象都有自己的数据成员,不过成员函数却是每个对象共享的.那么调用共享的成员函数如何找到自己的数据成员呢?答案是通过类中隐藏的this指针. 2 ...

  5. idea 远程代码调试

    声明一点:重要的事情说3遍 本地代码和服务器代码必须一致 本地代码和服务器代码必须一致 本地代码和服务器代码必须一致 第一步,创建remote 第二步.填写服务器信息 第三部.tomcat/bin/s ...

  6. SRS之SrsServer::cycle()

    1. SrsServer 相关类定义 1.1 SrsServer 类定义 /** * SRS RTMP server, initialize and listen, * start connectio ...

  7. 打开下载CA root 证书的链接失败

    下载CA root 证书 http://adip/certsrv server error or refuse to connect 这是由于AD上没有安装Active Directory Certi ...

  8. CSS、Bulma介绍

    文章目录 一.序章 二.CSS 基础 1. CSS 介绍 2. CSS 语法 3. CSS常用元素 1.颜色 2.字体大小 3.宽高 4.盒模型(单独拿出来讲) 5.背景 4.1样式和内容分离 4.2 ...

  9. wait/notify模拟线程池

    线程创建和销毁会消耗很多的资源,当我们创建线程时,会发现cpu利用率很高,为了节省资源的使用,使用线程池是一个比较好的选择,当有任务需要执行时,随机分配给一条线程去执行,也可以删除任务,获取任务数量等 ...

  10. rocketmq的linux搭建环境

    3.3. 上传解压[两台机器] # 上传 apache-rocketmq.tar.gz 文件至/usr/local # tar -zxvf apache-rocketmq.tar.gz -C /usr ...