IOI2021集训队作业 207PE

一棵树,每个点有个权值(v_i)

从根节点开始,每次遍历与走过的点联通的未走过的点,使得(v_i)的前缀和的最小值大于等于(0)

问是否能够到达(T)

(nle 10^5)


经典贪心。。。然而由于不知道怎么处理终点而搞了几天。。。

可以将一个点看成((a_i,b_i))的形式,表示前缀和的最小值为(-a_i),遍历了这个点可以得到(b_i)的收益。

如此定义((a_i,b_i))((a_j,b_j))优:

  1. (b_ige 0>b_j)
  2. (b_i,b_jge 0and a_i<a_j)
  3. (b_i,b_j<0and a_i+b_i>a_j+b_j)

先求出每个点的初始状态,每次找到最优的,和它的父亲合并。

这样适用于遍历整棵树的情况。如果只要求到达(T),把(b_T)设为无限大即可。


using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 200005
#define ll long long
#define INF 1000000000000000
int n,T;
struct EDGE{
	int to;
	EDGE *las;
} e[N*2];
int ne;
EDGE *last[N];
void link(int u,int v){
	e[ne]={v,last[u]};
	last[u]=e+ne++;
}
int fa[N];
void init(int x){
	for (EDGE *ei=last[x];ei;ei=ei->las)
		if (ei->to!=fa[x])
			fa[ei->to]=x,init(ei->to);
}
int dsu[N];
int getdsu(int x){return dsu[x]==x?x:dsu[x]=getdsu(dsu[x]);}
struct Status{ll a,b;int id;} s[N];
bool cmp(Status son,Status fa){
	if (fa.b>=0 && son.b>=0)
		return fa.a<son.a;
	if (fa.b<0 && son.b<0)
		return fa.a+fa.b>son.a+son.b;
	return fa.b>son.b;
}
Status q[N*2];
int nq;
void merge(int y,int x){
	dsu[x]=y;
	s[y].a=max(s[y].a,-s[y].b+s[x].a);
	s[y].b=s[y].b+s[x].b;
}
int main(){
	int Q;
	scanf("%d",&Q);
	while (Q--){
		scanf("%d%d",&n,&T);
		ne=0;
		memset(last,0,sizeof(EDGE*)*(n+1));
		for (int i=1;i<=n;++i){
			int x;
			scanf("%d",&x);
			if (x<0)
				s[i]={-x,x,i};
			else
				s[i]={0,x,i};
		}
		s[T].b=INF;
		for (int i=1;i<n;++i){
			int u,v;
			scanf("%d%d",&u,&v);
			link(u,v);
			link(v,u);
		}
		init(1);
		for (int i=1;i<=n;++i)
			dsu[i]=i;
		nq=0;
		for (int i=2;i<=n;++i)
			q[nq++]=s[i];
		make_heap(q,q+nq,cmp);
		while (nq){
			Status x=q[0];
			pop_heap(q,q+nq--,cmp);
			if (s[x.id].a!=x.a || s[x.id].b!=x.b || getdsu(x.id)!=x.id)
				continue;
			int y=getdsu(fa[x.id]);
			merge(y,x.id);
			if (y!=1){
				q[nq++]=s[y];			
				push_heap(q,q+nq,cmp);
			}
			else if (getdsu(T)==1)
				break;
		}
		if (s[1].a>0)
			printf("trapped
");
		else
			printf("escaped
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/jz-597/p/13865681.html