zoukankan      html  css  js  c++  java
  • ZJOI2008 骑士

    题目连接:戳我

    基环树上树形DP。

    强行断环边。。对于一个点u,断(u,to[u])边之后,是以to[u]为根的树形DP,如何处理不选这条边呢?当处理到u的时候,将dp[to[u]][1]设置成-0x3f3f3f3f即可。断了(fa[u],u)之后,是以u为根的树形DP,之后操作同上。

    备注:(dp[i][1])表示以i为根的子树的最大收获,选择i。(dp[i][0])则表示不选。

    状态转移感觉不必多说了qwq。。。。。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 1000010
    using namespace std;
    int n,m,now,t;
    int to[MAXN],head[MAXN],sum[MAXN],in[MAXN];
    bool done[MAXN],vis[MAXN];
    long long ans;
    long long dp[MAXN][2];
    struct Edge{int nxt,to;}edge[MAXN];
    inline void add(int from,int to){edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;}
    inline void search(int x)
    {
    	done[x]=1;
    	int v=to[x];
    	if(done[v]) now=x;
    	else search(v);
    }
    inline void solve(int x)	
    {
    	vis[x]=1,dp[x][0]=0,dp[x][1]=sum[x];
    	for(int i=head[x];i;i=edge[i].nxt)
    	{
    		int v=edge[i].to;
    		if(v==now) dp[v][1]=-0x3f3f3f3f;
    		else
    		{
    			solve(v);
    			dp[x][0]+=max(0*1ll,max(dp[v][1],dp[v][0]));
    			dp[x][1]+=max(0*1ll,dp[v][0]);
    		}
    	}
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&sum[i],&to[i]),add(to[i],i);
    	for(int i=1;i<=n;i++)
    	{
    		long long cur_ans=-0x7f7f7f7f;
    		if(vis[i]) continue;
    		search(i);
    		solve(now);
    		cur_ans=max(cur_ans,max(dp[now][0],dp[now][1]));
    		now=to[now];
    		solve(now);
    		cur_ans=max(cur_ans,max(dp[now][0],dp[now][1]));
    		ans+=cur_ans;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    接口的设置
    总结一下《vue的使用》
    标准时间对象的转换
    类数组转换为数组
    异步函数
    vue中moudles的作用及使用方法
    es5数组的新方法
    React JSX
    React更新元素 基础
    React将某段文字插入到某个元素里
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10404497.html
Copyright © 2011-2022 走看看