题意:一个树上建两个加油站。使得全部点到达其近期加油站的最大距离最小。

解法:二分答案。关键时二分时候,要最合理话布局两个点的位置,做法是处理出来树的直径,然后在直径两端分别向中间移动二分的x步的两个点布下加油站。

贪心能够证明正确性;

代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std; #define eps 1e-8
#define zero(_) (_<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=200010;
const LL INF=0x3FFFFFFF;
vector<int> vec[Max];
int n;
vector<int> diameter;
int rem[Max];
int rem1[Max];
int rem2[Max];
int dis[Max];
int st,en;
int dui[Max*2];
int now=0;
int count1=10;
void dfs(int u)
{
memset(rem,0,sizeof rem);
rem[u]=-1;
int left=0;
int right=1;
dui[0]=u;
dis[u]=0;
while(left<right)
{
for(int i=0; i<vec[dui[left]].size(); i++)
{
if(rem[vec[dui[left]][i]]==0)
{
rem[vec[dui[left]][i]]=dui[left];
dis[vec[dui[left]][i]]=dis[dui[left]]+1;
dui[right++]=vec[dui[left]][i];
}
}
left++;
}
} void ran1(int u,int* re)
{
int left=0;
int right=1;
dui[0]=u;
dis[u]=0;
re[u]=count1;
while(left<right)
{
if(dis[dui[left]]<now)
for(int i=0; i<vec[dui[left]].size(); i++)
{
if(re[vec[dui[left]][i]]!=count1)
{
re[vec[dui[left]][i]]=count1;
dis[vec[dui[left]][i]]=dis[dui[left]]+1;
if(dis[vec[dui[left]][i]]<now)
dui[right++]=vec[dui[left]][i];
}
}
left++;
}
} bool OK(int middle)
{
count1++;
now=middle;
ran1(diameter[middle],rem1);
ran1(diameter[diameter.size()-1-middle],rem2);
for(int i=1; i<=n; i++)
{
if(rem1[i]!=count1&&rem2[i]!=count1)
return false;
}
return true;
}
int main()
{
int t;
cin>>t;
while(t--)
{
for(int i=1;i<Max;i++)
vec[i].clear();
diameter.clear();
scanf("%d",&n);
for(int i=0; i<n-1; i++)
{
int a,b;
scanf("%d%d",&a,&b);
vec[a].push_back(b);
vec[b].push_back(a);
}
dfs(1);
int d=0;
for(int i=1; i<=n; i++)
{
if(dis[i]>d)
{
d=dis[i];
st=i;
}
}
dfs(st);
d=0;
for(int i=1; i<=n; i++)
{
if(dis[i]>d)
{
d=dis[i];
en=i;
}
}
while(en!=-1)
{
diameter.push_back(en);
en=rem[en];
}
int left=0,right=diameter.size();
while(left<=right)
{
int middle=(left+right)/2;
if(!OK(middle))
{
left=middle+1;
}
else
{
right=middle-1;
}
}
int a=diameter[left];
int b=diameter[diameter.size()-1-left];
if(a==b)
{
a=b==n?n-1:b+1;
}
//cout<<diameter.size()<<" "<<OK(0)<<OK(1)<<endl;
cout<<left<<" "<<a<<" "<<b<<'\n';
}
return 0;
}
/*
34
4
1 2
1 3
1 4
5
1 2
2 3
3 4
4 5
3
1 2
2 3
*/

hdu5044(二分)的更多相关文章

  1. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  2. BZOJ 2756: [SCOI2012]奇怪的游戏 [最大流 二分]

    2756: [SCOI2012]奇怪的游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3352  Solved: 919[Submit][Stat ...

  3. 整体二分QAQ

    POJ 2104 K-th Number 时空隧道 题意: 给出一个序列,每次查询区间第k小 分析: 整体二分入门题? 代码: #include<algorithm> #include&l ...

  4. [bzoj2653][middle] (二分 + 主席树)

    Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序列s. 回答Q个这样的询问:s的左端点在[a,b ...

  5. [LeetCode] Closest Binary Search Tree Value II 最近的二分搜索树的值之二

    Given a non-empty binary search tree and a target value, find k values in the BST that are closest t ...

  6. [LeetCode] Closest Binary Search Tree Value 最近的二分搜索树的值

    Given a non-empty binary search tree and a target value, find the value in the BST that is closest t ...

  7. jvascript 顺序查找和二分查找法

    第一种:顺序查找法 中心思想:和数组中的值逐个比对! /* * 参数说明: * array:传入数组 * findVal:传入需要查找的数 */ function Orderseach(array,f ...

  8. BZOJ 1305: [CQOI2009]dance跳舞 二分+最大流

    1305: [CQOI2009]dance跳舞 Description 一次舞会有n个男孩和n个女孩.每首曲子开始时,所有男孩和女孩恰好配成n对跳交谊舞.每个男孩都不会和同一个女孩跳两首(或更多)舞曲 ...

  9. BZOJ 3110 [Zjoi2013]K大数查询 ——整体二分

    [题目分析] 整体二分显而易见. 自己YY了一下用树状数组区间修改,区间查询的操作. 又因为一个字母调了一下午. 貌似树状数组并不需要清空,可以用一个指针来维护,可以少一个log 懒得写了. [代码] ...

随机推荐

  1. linq 分组

    var data = from r in listRecords group r by new { r.CampaignId, r.CityId, r.Gift_DistributorId, r.Pr ...

  2. Android开发问题-真机调试连接

    出现“no debuggable processes”可以: 1)尝试Tools->android->Enable ADB Intergration使之选中: 2)换一根数据线试试. 初次 ...

  3. 影响ERP成功实施的因素及实施方法

    一.影响ERP实施的因素 1.企业自身管理和认识上的问题.在ERP实施过程中没有用变革管理的理念和方法来策划和管理ERP的实施是导致ERP失败的主要原因. ERP作为一种管理工具他的实施本身就是操作手 ...

  4. Mongodb——文档数据库

    mongodb是一个文档数据库. mongo操作 多个修改操作,但每个修改携带的数据包较小,可操作考虑批量操作.bulkWrite()改善性能. MongoCollection是线程安全的. db.c ...

  5. JS——轮播图简单版

    1.小图标版本 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  6. [Windows Server 2008] 手工创建安全网站

    ★ 欢迎来到[护卫神·V课堂],网站地址:http://v.huweishen.com★ 护卫神·V课堂 是护卫神旗下专业提供服务器教学视频的网站,每周更新视频.★ 本节我们将带领大家:手工创建安全站 ...

  7. return和return false的区别

    1. return返回null,起到中断方法执行的效果,只要不return false事件处理函数将会继续执行,表单将提交2. return false,事件处理函数会取消事件,不再继续向下执行.比如 ...

  8. sql的四种连接方式

    1.内联接.(典型的联接运算,使用像 =  或 <> 之类的比较运算符).包括相等联接和自然联接. 内联接使用比较运算符根据每个表共有的列的值匹配两个表中的行.例如,检索 students ...

  9. 安卓手机安装charles安全证书

    本次安装使用小米mix2为例. 手机浏览器上安装: 第一种: 1.首先 设置好手机的charles代理   172.16.xxx.xxx   8888 2.要使用 打开非自带浏览器(夸克/QQ/UC手 ...

  10. B.4 集

    在.NET 3.5之前,框架中根本没有公开集(set)集合.如果要在.NET 2.0中表示集,通常会 使用 Dictionary<,> ,用集的项作为键,用假数据作为值..NET3.5的 ...