test20181029 宝藏

题意

分析

考场做法

一眼看出是支持换根的树形dp。

\(f(x,0/1)\)表示x及其子树中,从x出发,不一定/一定回到x的最大收益。

然后子树很好做。

换根的时候,我先计算后还原,需要考虑很多,调了很久。

后来知道可以用up,down状态转移,会好写一些,但要考虑得跟我先前打的差不多。

#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#include<cassert>
#define rg register
#define il inline
#define co const
#pragma GCC optimize ("O0")
using namespace std;
template<class T> il T read()
{
    T data=0;
	int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
		if(ch=='-')
			w=-1;
		ch=getchar();
	}
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return data*w;
}
template<class T> il T read(T&x)
{
	return x=read<T>();
}
typedef long long ll;
const int INF=0x7fffffff;

co int MAXN=3e5+7;

struct Edge
{
	int nx,to,w;
}E[MAXN<<1];
int head[MAXN],ecnt;

il void addedge(rg int x,rg int y,rg int w)
{
	E[++ecnt].to=y,E[ecnt].w=w;
	E[ecnt].nx=head[x],head[x]=ecnt;
}

int fa[MAXN],fw[MAXN];
int val[MAXN];

ll f[MAXN][2];
int maxv[MAXN],secv[MAXN];

il ll take(rg int y)
{
	return max(0LL,f[y][0]-fw[y]);
}

il ll fetch(rg int y)
{
	return max(0LL,f[y][1]-2*fw[y]);
}

il ll calc(rg int y)
{
	return take(y)-fetch(y);
}

il void dfs1(rg int x,rg int fath)
{
	fa[x]=fath;
	f[x][1]=val[x];
	for(rg int i=head[x];i;i=E[i].nx)
	{
		rg int y=E[i].to,w=E[i].w;
		if(y==fath)
		{
			fw[x]=w;
			continue;
		}
		dfs1(y,x);
		f[x][1]+=fetch(y);
	}
	f[x][0]=f[x][1];
	for(rg int i=head[x];i;i=E[i].nx)
	{
		rg int y=E[i].to;
		if(y==fath)
			continue;
		if(calc(y)>calc(secv[x]))
		{
			secv[x]=y;
			if(calc(secv[x])>calc(maxv[x]))
				swap(secv[x],maxv[x]);
		}
	}
	f[x][0]+=calc(maxv[x]);
}

ll fet[MAXN],calsec[MAXN],cal[MAXN];

il void dfs2(rg int x)
{
	if(fa[x])
	{	 // f[fa] shouldn't change
		fet[x]=fetch(x);
		cal[x]=calc(x);
		f[fa[x]][1]-=fet[x];
		f[fa[x]][0]-=fet[x];
		rg int w=fw[fa[x]];
		fw[fa[x]]=fw[x];
		f[x][1]+=fetch(fa[x]);
		f[x][0]=f[x][1];
		if(maxv[fa[x]]==x)
		{
			f[fa[x]][0]-=cal[x];
			f[fa[x]][0]+=calsec[fa[x]];
		}
		if(calc(fa[x])>calc(secv[x]))
		{
			secv[x]=fa[x];
			if(calc(secv[x])>calc(maxv[x]))
				swap(secv[x],maxv[x]);
		}
		calsec[x]=calc(secv[x]);
		f[x][0]+=calc(maxv[x]);
		
		f[fa[x]][1]+=fet[x]; // restore
		f[fa[x]][0]+=fet[x];
		fw[fa[x]]=w;
		if(maxv[fa[x]]==x)
		{
			f[fa[x]][0]-=calsec[fa[x]];
			f[fa[x]][0]+=cal[x];
		}
	}
	else
	{
		fet[x]=fetch(x);
		calsec[x]=calc(secv[x]);
		cal[x]=calc(x);
	}
	
	for(rg int i=head[x];i;i=E[i].nx)
	{
		rg int y=E[i].to;
		if(y==fa[x])
			continue;
		dfs2(y);
	}
}

int main()
{
  freopen("treasure.in","r",stdin);
  freopen("treasure.out","w",stdout);
	rg int n=read<int>();
	for(rg int i=1;i<n;++i)
	{
		rg int x=read<int>(),y=read<int>(),w=read<int>();
		addedge(x,y,w);
		addedge(y,x,w);
	}
	for(rg int i=1;i<=n;++i)
	{
		read(val[i]);
	}
	dfs1(1,0);
	dfs2(1);
/*	for(int i=1;i<=n;++i)
	{
		printf("%d:\n",i);
		printf(" f0=%lld\tf1=%lld\n",f[i][0],f[i][1]);
	}*/
	for(rg int i=1;i<=n;++i)
	{
		printf("%lld\n",f[i][0]);
	}
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

标解

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<bitset>
using namespace std;
typedef long long ll;
const int N=610000;
int fi[N],ne[N],len[N],to[N];
ll dp0[N],dp1[N];
ll ans[N],wushi0[N],wushi1[N],val[N];
int pE,n;
//0:考虑回到原点;1:不回到原点 
void addE(int u,int v,int l)
{
    pE++;to[pE]=v;len[pE]=l;
    ne[pE]=fi[u];fi[u]=pE;
}
void dfs(int u,int fa)
{
    ll mx=0;
    for (int j=fi[u];j;j=ne[j])
    {
        if (to[j]==fa) continue;
        dfs(to[j],u);
        if (dp0[to[j]]-2*len[j]>0) 
        {
            dp0[u]+=dp0[to[j]]-2*len[j];
            mx=max(mx,len[j]+dp1[to[j]]-dp0[to[j]]);
        }
        else mx=max(mx,dp1[to[j]]-len[j]);
    }
    dp0[u]+=val[u];
    dp1[u]=dp0[u]+mx;
}
void dfs2(int u,int fa,int le)
{
    ans[u]=max(dp0[u]+max(wushi1[u]-le,(ll)0),dp1[u]+max(wushi0[u]-le*2,(ll)0));
    ll mx1=0,mx2=0;
    for (int j=fi[u];j;j=ne[j])
    {
        if (to[j]==fa) continue;
        ll now;
        if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
            else now=dp1[to[j]]-len[j];
        if (now>mx1) {mx2=mx1;mx1=now;}
            else if (now>mx2) mx2=now;
    }
    ll now;
    if (wushi0[u]-2*le>0) now=le+wushi1[u]-wushi0[u];
        else now=wushi1[u]-le;
    if (now>mx1) {mx2=mx1;mx1=now;}
        else if (now>mx2) mx2=now;
    for (int j=fi[u];j;j=ne[j])
    {
        if (to[j]==fa) continue;
        wushi0[to[j]]=dp0[u]-max((ll)0,dp0[to[j]]-2*len[j])+max((ll)0,wushi0[u]-2*le);
        ll now;
        if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
            else now=dp1[to[j]]-len[j];
        if (now==mx1) wushi1[to[j]]=wushi0[to[j]]+mx2;
            else wushi1[to[j]]=wushi0[to[j]]+mx1;
    }
    for (int j=fi[u];j;j=ne[j])
        if (to[j]!=fa) dfs2(to[j],u,len[j]);
}
int main()
{
freopen("treasure.in","r",stdin);
freopen("treasure.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        int u,v,l;scanf("%d%d%d",&u,&v,&l);
        addE(u,v,l);addE(v,u,l);
    }
    for (int i=1;i<=n;i++) scanf("%d",&val[i]);
    dfs(1,0);
    for (int j=fi[1];j;j=ne[j])
        if (dp0[to[j]]-2*len[j]>0) 
            wushi0[to[j]]=dp0[1]-(dp0[to[j]]-2*len[j]);
                else wushi0[to[j]]=dp0[1];
    ll mx1=0,mx2=0;
    for (int j=fi[1];j;j=ne[j])
    {
        ll now;
        if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
            else now=dp1[to[j]]-len[j];
        if (now>mx1) {mx2=mx1;mx1=now;}
            else if (now>mx2) mx2=now;
    }
    for (int j=fi[1];j;j=ne[j])
    {
        ll now;
        if (dp0[to[j]]-2*len[j]>0) now=len[j]+dp1[to[j]]-dp0[to[j]];
            else now=dp1[to[j]]-len[j];
        if (now==mx1) wushi1[to[j]]=wushi0[to[j]]+mx2;
            else wushi1[to[j]]=wushi0[to[j]]+mx1;
    }
    ans[1]=dp1[1];
    for (int j=fi[1];j;j=ne[j]) dfs2(to[j],1,len[j]);
    for (int i=1;i<=n;i++) printf("%lld\n",ans[i]);
    return 0;
}

posted on 2018-10-29 17:59  autoint  阅读(117)  评论(0编辑  收藏  举报

导航