题意:

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

思路:

树的直径类题目。

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

而且要切一定切在树的直径上,如果不切在直径上,那有一个团的最场距离不就是(直径长度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. Java线程之Timer

    简述 java.util.Timer是一个定时器,用来调度线程在某个时间执行.在初始化Timer时,开启一个线程循环提取TaskQueue任务数组中的任务, 如果任务数组为空,线程等待直到添加任务: ...

  2. hadoop+zookeeper+hbase伪分布式安装

    基本安装步骤 安装包下载 从大数据组件下载地址下载以下组件安装包 hadoop-2.6.0-cdh5.6.0.tar.gz hbase-1.0.0-cdh5.6.0.tar.gz zookeeper- ...

  3. shell编程-定时任务(备份数据库)

    计划任务定时备份,删除等操作: #crontab -e #注意 会区分用户 默认在root用户登录用的是root权限用户的计划任务, 如果想在postgres备份 应使用postgres用户权限, 设 ...

  4. 05.用两个栈实现队列 Java

    题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. 思路 进栈: 直接进stack1 出栈: 若stack2不为空,则出栈. 否则,当stack1不为空时, ...

  5. python3笔记二十二:正则表达式之函数

    一:学习内容 re.match函数 re.search函数 re.findall函数 二:re.match函数 需要导入包:import re 1.格式:match(pattern,string,fl ...

  6. ssh不输入密码

    要通过跳转机器远程其他的机器 不方便使用秘钥 每次都要输入密码也很烦 使用sshpass可以复制一行命令就直接登录了 我的跳板机是Centos7安装sshpass很简单 直接如下搞定 yum inst ...

  7. DatabaseLibrary数据库测试

    DatabaseLibrary常用关键字 关  键  字 描   述 Connect To Database 连接数据库 Connect To Database Using Custom Params ...

  8. Copy-On-Write in Swift

    Premature optimisation is the root of all evil. But, there are moments where we need to optimise our ...

  9. LC 712. Minimum ASCII Delete Sum for Two Strings

    Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal. ...

  10. 小程序API:wx.showActionSheet 将 itemList动态赋值

    1.发现问题: 小程序调用API:wx.showActionSheet 时发现无论如何都不能将其属性itemList动态赋值. 2.分析问题: 首先我认为可能是格式的问题,itemList必须要求格式 ...