luogu P1084 疫情控制

#include<bits/stdc++.h>
#define MAXN 70005
using namespace std;

int n,h[MAXN],tot,ff[MAXN][25],cost[MAXN][25],m,g[MAXN],l,r,mid,best,sum[MAXN],f[MAXN];
int found[MAXN],vis[MAXN],al;
struct node{
	int from,to,cost,next;
}e[MAXN << 1];

int js,js2;
struct node2{
	int ch,rest;
}q[MAXN],q2[MAXN];

bool cmp(int x , int y){
	return cost[x][0] < cost[y][0];
}

bool cmp2(node2 x , node2 y){
	return x.rest - cost[x.ch][0] < y.rest - cost[y.ch][0];
}

bool cmp3(node2 x , node2 y){
	return x.rest - cost[x.ch][0] > y.rest - cost[y.ch][0];
}

/*
¨¬¡ãD?1?¡ê¡Á¡è?¨¹¡Á¨®¨º¡Â??¡ä¨®¡ê???¨®?
??¡¤¡§¡êo?t¡¤?¡äe¡ã?+¨¦????D??
?t¡¤?????¨°??¨¦?¨´D¨¨¡Á?¨¦¨´¨º¡À??
??¡Á¨¦?¨¹?¨®??¨¢|¨ª¨´?¨´?¨²¦Ì?¡Á?
¨¢????¨²¦Ì?¡êo1¡ê??¨¦¨°?¦Ì??¨´?¨²¦Ì? 2¡ê?2??¨¦¨°?¦Ì??¨´?¨²¦Ì?
1¡ê?¦Ì??¨´?¨²¦Ì?¨º¡À¡ê????¡è?????¨²¦Ì?¦Ì??¨´?¨²¦Ì??¨´¡Á¨®?¨´¨º¡ê??¦Ì?¨º¡À??¨°??¡ã?¨´¨º??¨´¡Á¨®
2, ??¨¢|¨ª¨´¨¦?¡Á??¨ªDD¨¢?

check¡êo
?¨¨¡ä|¨¤¨ª2¨¤¨¤?¨²¦Ì?¡ê?¨º¡Â?¡ã¡Áo¡ê?¦Ì?¦Ì?????¨°?¡Á¨®??¨®D¡À??2??¡ê?¦Ì?¦Ì????¨´¨º?¦Ì??¨´?¨´¡Á¨®¡Á¨®¨º¡Â 
*/

void add(int x , int y , int z){
	tot++;
	e[tot].from = x;
	e[tot].to = y;
	e[tot].cost = z;
	e[tot].next = h[x];
	h[x] = tot;
}

void get(int now , int fa){
	ff[now][0] = fa;
	int kk = 0;
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(e[i].to == fa)continue;
		kk++;
	}
	for(int i = h[now] ; i != (-1) ; i = e[i].next){
		if(e[i].to == fa)continue;
		cost[e[i].to][0] = e[i].cost;
		if(kk == 1)f[e[i].to] = f[now];
		else f[e[i].to] = e[i].to;
		get(e[i].to , now);
	}
}

void init(){
	memset(h , -1 , sizeof(h));tot = 0;
	memset(cost , 0 , sizeof(cost));
	cin>>n;int u,v,w;
	for(int i = 1 ; i < n ; i++){
		cin>>u>>v>>w;
		add(u , v , w) , add(v , u , w);		
	}
	for(int i = h[1] ; i != (-1) ; i = e[i].next)f[e[i].to] = e[i].to;
	get(1 , 1);
	for(int j = 1 ; j <= 23 ; j++)
		for(int i = 1 ; i <= n ; i++)
			ff[i][j] = ff[ff[i][j - 1]][j - 1];
	for(int j = 1 ; j <= 23 ; j++)
		for(int i = 1 ; i <= n ; i++)
			cost[i][j] = cost[i][j - 1] + cost[ff[i][j - 1]][j - 1];
}

int check(int dx){
	for(int i = 1 ; i <= n ; i++)sum[i] = 0;
	int zz,now;al = js = js2 = 0;
	for(int i = 1 ; i <= m ; i++){
		zz = dx , now = g[i];
		for(int j = 23 ; j >= 0 ; j--)
			if(cost[now][j] <= zz && ff[now][j] != 1)
				zz -= cost[now][j] , now = ff[now][j];
		if(ff[now][0] == 1 && zz >= cost[now][0])q[++js].ch = now , q[js].rest = zz - cost[now][0];
		else sum[f[now]]++;
	}
	sort(q + 1 , q + 1 + js , cmp2);
	for(int i = 1 ; i <= js ; i++){
		if(sum[q[i].ch] == 0 && q[i].rest < cost[q[i].ch][0])sum[q[i].ch]++;
		else q2[++js2] = q[i];
	}
	for(int i = h[1] ; i != (-1) ; i = e[i].next)if(!sum[e[i].to])found[++al] = e[i].to;
	swap(q , q2) , swap(js , js2);
	sort(found + 1 , found + 1 + al , cmp);
	sort(q + 1 , q + 1 + js , cmp2);
	zz = 1 , now = 1;
	while(zz <= al && now <= js){
		if(q[now].rest >= cost[found[zz]][0]){
			zz++ , now++;
		}
		else now++;
	}
	if(zz > al)return 1;
	else return 0;
	
	return 1;
}

void solve(){
	cin>>m;
	for(int i = 1 ; i <= m ; i++)cin>>g[i];
	l = 0 , r = 50000000 , best = (-1);
	check(9);
	while(l <= r){
		mid = (l + r) >> 1;
		if(check(mid))r = mid - 1 , best = mid;
		else l = mid + 1;
	}
	cout<<best<<endl;
}

int main(){
	init();
	solve();
}

做法1 O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)直接二分,然后全部往上跳,然后再在根节点处理一下就好了

做法2 O ( n l o g n ) O(nlogn) O(nlogn)直接先处理出每个军队到根节点的距离再排序,然后可以二分到那个节点可以上根,然后就复杂的处理一下。。。。。打是不可能打的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值