树上选两点(使最短)树的直径+bfs
题意:
给你一颗树,让你放两个点,放在哪里的时候任意点到某个最近的消防站最远值最小。
思路:
树的直径类题目。
首先我们想两个点会把整棵树分成两个团,所以肯定会在树的某个链上切开。
而且要切一定切在树的直径上,如果不切在直径上,那有一个团的最场距离不就是(直径长度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的更多相关文章
- Codeforces 1182D Complete Mirror 树的重心乱搞 / 树的直径 / 拓扑排序
题意:给你一颗树,问这颗树是否存在一个根,使得对于任意两点,如果它们到根的距离相同,那么它们的度必须相等. 思路1:树的重心乱搞 根据样例发现,树的重心可能是答案,所以我们可以先判断一下树的重心可不可 ...
- poj2631 树的直径 + bfs
//Accepted 492 KB 0 ms //树的直径 bfs #include <cstdio> #include <cstring> #include <iost ...
- 从Trie树(字典树)谈到后缀树
转:http://blog.csdn.net/v_july_v/article/details/6897097 引言 常关注本blog的读者朋友想必看过此篇文章:从B树.B+树.B*树谈到R 树,这次 ...
- java实现哈弗曼树和哈夫曼树压缩
本篇博文将介绍什么是哈夫曼树,并且如何在java语言中构建一棵哈夫曼树,怎么利用哈夫曼树实现对文件的压缩和解压.首先,先来了解下什么哈夫曼树. 一.哈夫曼树 哈夫曼树属于二叉树,即树的结点最多拥有2个 ...
- 树&二叉树&哈夫曼树
1.树 需要注意的两点:n(n>=0)表示结点的个数,m表示子树的个数 (1)n>0时,树的根节点是唯一的. (2)m>0时,子树的个数没有限制. 结点的度和树的度 (1)结点的度是 ...
- [算法]从Trie树(字典树)谈到后缀树
我是好文章的搬运工,原文来自博客园,博主July_,地址:http://www.cnblogs.com/v-July-v/archive/2011/10/22/2316412.html 从Trie树( ...
- BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...
- [转]B树(多向平衡查找树)详解
B-树是对2-3树数据结构的扩展.它支持对保存在磁盘或者网络上的符号表进行外部查找,这些文件可能比我们以前考虑的输入要大的多(以前的输入能够保存在内存中). (B树和B+树是实现数据库的数据结构,一般 ...
- 树-二叉搜索树-AVL树
树-二叉搜索树-AVL树 树 树的基本概念 节点的度:节点的儿子数 树的度:Max{节点的度} 节点的高度:节点到各叶节点的最大路径长度 树的高度:根节点的高度 节点的深度(层数):根节点到该节点的路 ...
随机推荐
- vue整合adminLTE
前端框架AdminLTE 中文教程 如何用vue整合adminlte模板 1.adminlte 下载地址 : https://github.com/almasaeed2010/AdminLTE/rel ...
- jQuery属性操作之值操作
值操作是对DOM属性value进行读取和设置操作. 比如html(). text(). val(). 1. html 1. 1 html()获取值 返回值:String 描述:获取集合中第一个匹配元素 ...
- IDEA如何将写好的java类(UDF函数)打成jar包上传linux
一.编写一个UDF函数,实现将字符串大写转小写 import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; ...
- C++入门经典-例7.6-this指针,同一个类的不同对象数据
1:对于类的非静态成员,每个对象都有自己的一份拷贝,即每个对象都有自己的数据成员,不过成员函数却是每个对象共享的.那么调用共享的成员函数如何找到自己的数据成员呢?答案是通过类中隐藏的this指针. 2 ...
- idea 远程代码调试
声明一点:重要的事情说3遍 本地代码和服务器代码必须一致 本地代码和服务器代码必须一致 本地代码和服务器代码必须一致 第一步,创建remote 第二步.填写服务器信息 第三部.tomcat/bin/s ...
- SRS之SrsServer::cycle()
1. SrsServer 相关类定义 1.1 SrsServer 类定义 /** * SRS RTMP server, initialize and listen, * start connectio ...
- 打开下载CA root 证书的链接失败
下载CA root 证书 http://adip/certsrv server error or refuse to connect 这是由于AD上没有安装Active Directory Certi ...
- CSS、Bulma介绍
文章目录 一.序章 二.CSS 基础 1. CSS 介绍 2. CSS 语法 3. CSS常用元素 1.颜色 2.字体大小 3.宽高 4.盒模型(单独拿出来讲) 5.背景 4.1样式和内容分离 4.2 ...
- wait/notify模拟线程池
线程创建和销毁会消耗很多的资源,当我们创建线程时,会发现cpu利用率很高,为了节省资源的使用,使用线程池是一个比较好的选择,当有任务需要执行时,随机分配给一条线程去执行,也可以删除任务,获取任务数量等 ...
- rocketmq的linux搭建环境
3.3. 上传解压[两台机器] # 上传 apache-rocketmq.tar.gz 文件至/usr/local # tar -zxvf apache-rocketmq.tar.gz -C /usr ...