社区讨论

40分代码求调(码风简洁)

P1084[NOIP 2012 提高组] 疫情控制参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@loqutnpv
此快照首次捕获于
2023/11/09 15:15
2 年前
此快照最后确认于
2023/11/09 17:34
2 年前
查看原帖
C
#include<bits/stdc++.h>

#define int long long

#define re register

using namespace std;

inline int read(){
	int x = 0,f = 1;char c = getchar();
	for(;!isdigit(c);c = getchar())if( c == '-' )f = -1;
	for(;isdigit(c);c = getchar())x = (x << 1) + (x << 3) + c - '0';
	return x * f;
}

const int N = 6e4 + 5;
typedef pair<int,int> pii;

int n,m,mxt,ans,T;
int ph,pt,ps;
int id[N];
int fa[N][20],dis[N][20],dep[N];
bool status[N],need[N],still[N];
int tim[N];
pii h[N];
int head[N << 1],cnt;
struct edge{
	int to,next,w;
}e[N << 1];

inline void add(int from,int to,int w){
	e[++ cnt] = (edge){to , head[from] , w};
	head[from] = cnt;
}

inline void init(){
	queue<int> Q;
	Q.push(1);
	dep[1] = 1;
	while( !Q.empty() ){
		int x = Q.front();
		Q.pop();
		for(int i = head[x];i;i = e[i].next){
			int to = e[i].to;
			if( dep[to] )continue;
			dep[to] = dep[x] + 1;
			fa[to][0] = x;
			dis[to][0] = e[i].w;
			for(int j = 1;j <= T;j ++){
				fa[to][j] = fa[fa[to][j - 1]][j - 1];
				dis[to][j] = dis[to][j - 1] + dis[fa[to][j - 1]][j - 1];
			}
			Q.push( to );
		}
	}
}

inline bool dfs(int x){
	bool leave = 0;
	if( status[x] )return 1;
	for(int i = head[x];i;i = e[i].next){
		int to = e[i].to;
		if( dep[to] < dep[x] )continue;
		leave = 1;
		if( !dfs( to ) )return 0;
	}
	if( !leave )return 0;
	else return 1;
}

inline bool check(int lim){
	memset( status , 0 , sizeof( status ) );
	memset( tim , 0 , sizeof( tim ) );
	memset( still , 0 , sizeof( still ) );
	memset( h , 0 , sizeof( h ) );
	memset( need , 0 , sizeof( need ) );
	ph = pt = ps = 0;
	for(int i = 1;i <= m;i ++){
		int x = id[i],cnt = 0;
		for(int j = T;j >= 0;j --){
			if( fa[x][j] > 1 && cnt + dis[x][j] <= lim ){
				cnt += dis[x][j];
				x = fa[x][j];
			}
		}
		if( fa[x][0] == 1 && cnt + dis[x][0] <= lim )h[++ ph] = make_pair( lim - cnt - dis[x][0] , x );
		else status[x] = 1;
	}
	for(int i = head[1];i;i = e[i].next){
		int to = e[i].to;
		if( !dfs( to ) )need[to] = 1;
	}
	sort( h + 1 , h + ph + 1 );// first is rest time , second is idx
	for(int i = 1;i <= ph;i ++){
		if( need[h[i].second] && h[i].first < dis[h[i].second][0] )
			need[h[i].second] = 0;
		else tim[++ pt] = h[i].first;
	}
	for(int i = head[1];i;i = e[i].next){
		int to = e[i].to;
		if( need[to] )still[++ ps] = dis[to][0];
	}
	if( pt < ps )return 0;
	sort( tim + 1 , tim + pt + 1 );
	sort( still + 1 , still + ps + 1 );
	int pi = 1,pj = 1;
	while( pi <= pt && pj <= ps ){
		if( tim[pi] >= still[pj] )pi ++,pj ++;
		else pi ++;
	}
	if( pj > ps )return 1;
	return 0;
}
	
signed main(){
	int l = 0,r = 0,exist = 0;
	n = read();
	T = log2(n) + 1;
	for(int i = 1;i < n;i ++){
		int u = read(),v = read(),w = read();
		add( u , v , w );
		add( v , u , w );
		mxt += w;
	}
	r = mxt;
	init();
	m = read();
	for(int i = 1;i <= m;i ++)id[i] = read();
	while( l <= r ){
		int mid = ( l + r ) >> 1;
		if( check( mid ) ){
			exist = 1;
			ans = mid;
			r = mid - 1;
		}
		else l = mid + 1;
	}
	if( !exist )cout << -1 << endl;
	else printf("%lld\n",ans);
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...