题意:

题目描述

H 国有n个城市,这n个城市用n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。

请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

输入格式

第一行一个整数n,表示城市个数。

接下来的n-1行,每行3个整数u,v,w,每两个整数之间用一个空格隔开,表示从城市u到城市v有一条长为w的道路。数据保证输入的是一棵树,且根节点编号为1

接下来一行一个整数m,表示军队个数。

接下来一行m个整数,每两个整数之间用一个空格隔开,分别表示这m个军队所驻扎的城市的编号。

输出格式

共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。

数据范围

洛咕,即官方数据范围:

LOJ:

吐槽:

LOJ这数据……真的天坑我艹

看LOJ数据以为$O(n^2logn)$只有30很虚,结果去看官方数据有60……

然后我$O(nlogn)$的正解不仅要开longlong还被卡常卡成95,在洛咕秒过……

SBLOJ!

题解:

由于军队可以同时移动,所以题目要求的就是使最大值最小,这种最优化问题明显二分答案;

一个结论是军队肯定离根节点越近控制的点越多,即深度越小越优,所以军队选择的策略肯定是向上走;

这样贪心的思路就是让尽量多的军队走到根节点,然后走到那些没有军队的根节点的子节点上,这样子就控制了以那个子节点为根的整个子树;

但是有些军队在时间限制内是走不到根节点的,所以要按照走不走得到根节点分类,如果走不到就留在能走到的最高的点,把这些点设为已被控制,走的到的暂时放在根节点,然后记录这些军队是从根节点的哪个子节点走上来的;

这时可以dfs一遍求出哪些点已经被控制了,注意如果一个点的所有子节点都被控制了那么这个点也算被控制了,然后记录下所有没被控制的根节点的子节点;

按照剩余的时间给所有能到达根节点的军队排序,按照到根节点的距离给没被控制的那些子节点排序,明显剩余时间多军队的去支援到根节点距离远的子节点是最优的;

但是还有个问题,就是有些军队去支援后自己来源的那个子节点反而没有军队去控制;

因此排序时要从小到大,然后优先让每个军队向下回到自己来源的那个子节点(这样做就可以忽略上到根节点又回去的过程,所以时间肯定符合),否则去支援其他子节点,最后判断能否控制所有子节点即可。

这里快速求距离用树上倍增实现。

讲的比较复杂,代码里细节也很多,写的时候要注意。

代码:

(LOJ被卡常95分,不加读入优化90分)

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 10000000000000000
#define eps 1e-9
using namespace std;
typedef long long ll;
struct edge{
int v,w,next;
}a[];
struct node{
ll v;
int id;
friend bool operator <(node a,node b){
return a.v<b.v;
}
}ar[],nd[];
int n,m,u,v,w,tot=,cnt=,_cnt=,arm[],fa[][],head[];
ll ans=-,l,r,sum=,dis[][];
bool isin[];
char buffer[],*hd,*tl;
inline char Getchar(){
if(hd==tl){
int len=fread(buffer,,,stdin);
hd=buffer,tl=hd+len;
if(hd==tl)
return EOF;
}
return *hd++;
}
inline int rd(){
register int x=;
char c;
do c=Getchar();
while(!isdigit(c));
do{
x=(x<<)+(x<<)+(c^);
c=Getchar();
}while(isdigit(c));
return x;
}
void add(int u,int v,int w){
a[++tot].v=v;
a[tot].w=w;
a[tot].next=head[u];
head[u]=tot;
}
void dfs(int u,int ff,int ds){
fa[u][]=ff;
dis[u][]=ds;
for(int i=;i<=;i++){
fa[u][i]=fa[fa[u][i-]][i-];
dis[u][i]=dis[u][i-]+dis[fa[u][i-]][i-];
}
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=ff){
dfs(v,u,a[tmp].w);
}
}
}
void dfstf(int u,int fa){
bool t1=true,t2=false;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(v!=fa){
dfstf(v,u);
t1&=isin[v];
t2=true;
}
}
if(t1&&t2&&u!=)isin[u]=true;
}
bool chk(ll k){
int nw,ret=;
ll d=;
for(int i=;i<=n;i++)isin[i]=false;
cnt=_cnt=;
for(int i=;i<=m;i++){
nw=arm[i];
d=;
for(int j=;j>=;j--){
if(fa[nw][j]&&d+dis[nw][j]<=k){
d+=dis[nw][j];
nw=fa[nw][j];
}
}
if(nw!=)isin[nw]=true;
else{
int vv=arm[i];
for(int j=;j>=;j--){
if(fa[vv][j]>)vv=fa[vv][j];
}
ar[++cnt].v=k-d;
ar[cnt].id=vv;
}
}
dfstf(,);
for(int tmp=head[];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(!isin[v]){
nd[++_cnt].v=a[tmp].w;
nd[_cnt].id=v;
}
}
sort(ar+,ar+cnt+);
sort(nd+,nd+_cnt+);
nd[_cnt+].v=inf;
for(int i=;i<=cnt;i++){
if(!isin[ar[i].id])isin[ar[i].id]=true;
else if(ar[i].v>=nd[ret].v)isin[nd[ret].id]=true;
while(isin[nd[ret].id])ret++;
}
return ret>_cnt;
}
int main(){
memset(head,-,sizeof(head));
//scanf("%d",&n);
n=rd();
for(int i=;i<n;i++){
//scanf("%d%d%d",&u,&v,&w);
u=rd(),v=rd(),w=rd();
add(u,v,w);
add(v,u,w);
sum+=w;
}
//scanf("%d",&m);
m=rd();
for(int i=;i<=m;i++)arm[i]=rd();//scanf("%d",&arm[i]);
l=,r=sum;
dfs(,,);
while(l<=r){
ll mid=(l+r)/;
if(chk(mid))ans=mid,r=mid-;
else l=mid+;
}
printf("%lld",ans);
return ;
}

最新文章

  1. IIS中查看W3P.exe进程对应的应用程序池的方法
  2. HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
  3. Leetcode 155 Min Stack 小顶堆+栈,优先队列实现 难度:0
  4. 做java工作整整1年了,看到了大牛的奋斗历程,我感觉自己又有目标了
  5. SpringMVC后缀
  6. Spark和Hadoop作业之间的区别
  7. javascript回车完美实现tab切换功能
  8. 题目1069:查找学生信息(STL的map简单应用)
  9. ajax的GET和POST请求
  10. android控件上面实现提醒信息
  11. Android 开发笔记 “Sqlite Cursor 使用”
  12. 两个实验操作系统-ubuntu在安装配置pintos
  13. hdu_5792_World is Exploding(树状数组+逆序对)
  14. Hidden Word
  15. Markdown - 语法简介
  16. error: command &#39;gcc&#39; failed with exit status 1
  17. 首席科学家马丁•福勒(Martin Fowler)
  18. 2018.12.31 NOIP训练 czy的后宫5(树形dp)
  19. Android -- Canvas java.lang.UnsupportedOperationException
  20. ng-class ng-style

热门文章

  1. js input 只能输入数字
  2. 页面定制CSS代码初探(三):设置正文最小高度
  3. jsp+jdbc实现用户登录
  4. css——定位
  5. 【XSY2692】杨柳 - 网络流
  6. KVM虚拟机相关步骤
  7. Shell(三)流程控制
  8. 基于bootstrap的分页组件-Bootstrap Paginator
  9. 2.WHERE中使用=,&gt;,&gt;=,&lt;,&lt;=,&lt;&gt;,!=比较符号
  10. 在Windows系统下搭建Redis集群