【NOIP2014模拟11.1B组】魏传之长坂逆袭

这题有两种方法可以实现。
第一种是直接DFS。
我们遍历整个树,然后对于一颗子树,求出从根到达子树的叶子节点的所有方案中的最大值,然后再从根节点开始遍历,并贪心求答案。
我们可以知道越接近根节点,它的子树大小越大,所以我们可以从根节点开始贪心看每条路径设置的陷阱数量的最大值,然后在继续DFS.。
第二种方法与第一种类似,就是用人工栈实现。

本以为dfs会爆栈的。。。

所以就打了个人工栈。。。

WDF!!!

上标:

#include<cstdio>
#define N 500010
#define ll long long
#define max(x,y) x>y ? x:y
using namespace std;
struct node{int v,fr,t;}e[N<<1];
int n,tail[N],cnt=0,fa[N],z[N],top=1,x;
ll ma[N],ad[N],tb=0,ans=0;
bool bz[N];

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

inline void add(int u,int v,int t) {e[++cnt]=(node){v,tail[u],t}; tail[u]=cnt;}

int main()
{
	freopen("wei.in","r",stdin);
	freopen("wei.out","w",stdout);
	n=read();
	for (int i=1,u,v,t;i<n;i++)
	{
		u=read(),v=read(),t=read();
		add(u,v,t),add(v,u,t);
	}
	z[1]=1;
	while (top)
	{
		x=z[top];
		if (bz[x])
		{
			for (int p=tail[x];p;p=e[p].fr)
				ma[x]=max(ma[x],ma[e[p].v]);
			top--;
		}
		else
		{
			bz[x]=1;
			for (int p=tail[x],v;p;p=e[p].fr)
				if (!bz[v=e[p].v])
				{
					ma[v]=ma[x]+e[p].t;
					tb=max(tb,ma[v]);
					fa[v]=x,z[++top]=v;
				}
		}
	}
//	for (int i=1;i<=n;i++) printf("%d ",ma[i]);puts("");
	z[top=1]=1;
	while (top)
	{
		x=z[top--];
		for (int p=tail[x],v;p;p=e[p].fr)
			if ((v=e[p].v)!=fa[x])
			{
				ans+=tb-ma[v]-ad[x];
				ad[v]=tb-ma[v];
				z[++top]=v;
			}
	}
	printf("%lld
",ans);
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817585.html