hdu 6326 Monster Hunter 流水线排序+节点合并

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ccsu_cat/article/details/81325469

多校三第H题,题意有n个节点构成一棵树,除了节点1每个节点有个怪兽和两个属性a,b,表示杀死这个怪兽自己要先扣血a,扣完血后自己的血不能是负数,再加血b,从1节点出发,不能跨越节点,求至少需要多少血量才能杀死所有怪兽。

思路:假设可以跨越节点杀怪兽,当a<b时,杀完怪兽后自己反而加血,因此当a<b时优先杀a越小的怪兽,当a>=b时,优先杀b越大的,这个排序方法就是流水线排序,和多校1第二题排序法一样。现在加上限制条件,不能跨越节点杀怪兽,先将所有节点排好序p1 p2 p3 ...pn,先出p1,从一号节点出发,如果p1可以直接到达,那么就先杀p1,如果p1不能直接到达,就找到p1的父亲,如果p1的父亲被杀了,下一个肯定杀p1,怎么搞定这个操作呢,只要将p1与其父亲这两个节点合并就好了,就表示杀其父亲也顺便把p1杀了,因此所有操作就是个不停的合并节点的过程,用优先队列实现其过程就好了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long LL;
const LL inf=1e14;
const int maxn=2e5+10;
struct node
{
	LL a,b;
	int u,num; 
	bool operator<(const node& t)const//流水线排序 
	{
		if(a<b)
		{
			if(t.a<t.b)
			return a>t.a;
			return false;
		}
		else
		{
			if(t.a>=t.b)
			return b<t.b;
			return true;
		}
	}
	void operator+=(const node& t)//节点合并,节点的a保存的是至少需要a的血量才能杀死这个节点的怪兽 
	{
		LL na=max(a,a-b+t.a),nb=b+t.b-t.a-a+na;
		a=na,b=nb;
	}
}a[maxn];
int vis[maxn],fa[maxn],del[maxn];
vector<int>G[maxn];
priority_queue<node>q;
void init(int n)
{
	for(int i=0;i<=n;i++)
	vis[i]=del[i]=0,G[i].clear();
}
void dfs(int u,int father)
{
	fa[u]=father;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i];
		if(v!=father) 
		dfs(v,u);
	}
}
int F(int u)
{
	if(del[fa[u]])//父亲也被删除,就找爷爷 
	return fa[u]=F(fa[u]);//并查集路径压缩 
	return fa[u];
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,u,v,pos=0;
		scanf("%d",&n);
		init(n);
		for(int i=2;i<=n;i++)
		{
			scanf("%lld%lld",&a[i].a,&a[i].b);	
			a[i].u=i,a[i].num=0;
		}
		for(int i=1;i<n;i++)
		{
			scanf("%d%d",&u,&v);
			G[u].push_back(v);
			G[v].push_back(u);
		}
		dfs(1,0);
		a[1].a=a[1].b=a[1].num=0,a[1].u=1;
		for(int i=2;i<=n;i++)
		q.push(a[i]);
		while(!q.empty())
		{
			node t=q.top();q.pop();
			if(del[t.u])continue;  //已经被删除 
			if(t.num!=vis[t.u])continue;   //这个节点已经被更新 
			del[t.u]=1;   //删除这个节点 
			int f=F(t.u);  //找到其父亲 
			a[f]+=a[t.u];
			if(f>1)
			{
				a[f].num=vis[f]=++pos;//更新 f 节点 
				q.push(a[f]);
			}
		}
		printf("%lld\n",a[1].a);
	}
}

猜你喜欢

转载自blog.csdn.net/ccsu_cat/article/details/81325469