zoukankan      html  css  js  c++  java
  • 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:
    ",i);
    		printf(" f0=%lld	f1=%lld
    ",f[i][0],f[i][1]);
    	}*/
    	for(rg int i=1;i<=n;++i)
    	{
    		printf("%lld
    ",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
    ",ans[i]);
        return 0;
    }
    
    静渊以有谋,疏通而知事。
  • 相关阅读:
    ajax标准写法
    javascript序列化表单追加参数
    javascript获取url参数的方式
    jmeter实现跨线程组传递参数
    代码扫描工具SonarQube+Scanner的基本安装与应用
    给定一个非空正整数的数组,把数值与出现的次数存在一个新的字典中,并按照出现的次数排序
    定义一个函数,实现整数列表中偶数在左边,奇数在右边(不借助其它列表)
    python-leetcode1在一个整数数组中找出两数之和等于目标值,并把两数下标存在list中返回
    python根据key对字典进行排序
    python实现对浮点型的四舍五入
  • 原文地址:https://www.cnblogs.com/autoint/p/9872116.html
Copyright © 2011-2022 走看看