2017.9.7 骑士 思考记录

这个题其实一个月前就想写了、但当时看到环基树就吓跑了、、

但其实这个题除了环要找出来单独跑一边dp、、别的就真的没了

先把环找出来(由于只有一个环,所以直接dfs)

然后对环上的每个点做一遍子树的dp

然后把环拆下来,枚举第一个点的状态、从这个点左边一直做到这个点右边

然后就没了、、注意它可能有多个子集、、  

一个dp被我活生生写成了码农题、别的题解都40行、但还是调过了、码力看来还是可以的、

码:

#include<iostream>
#include<cstdio>
using namespace std;
#include<vector>
#define N 1000005
#define ll long long
vector<int>v[N],vv;
ll fu[N],h[N],f[N][3],g[N][3],n,a[N],x,ans,j,yici,d[N];
bool vis[N]; 
void dfs(int o,int fa,int dis)
{
	d[o]=dis;
	fu[o]=fa;
	vis[o]=1;
	int i;
	for(i=0;i<v[o].size();i++)
  {
  	int nd=v[o][i];
  	if(nd==fa)continue;
	  if(vis[nd])
  	{
	  if(yici==0&&d[nd]>d[o]) 
	  {
	  yici=1;
  		int x=nd;
  		while(x!=o)
  		{
  		vv.push_back(x);
  		h[x]=1;
  		x=fu[x];	
		}
        h[x]=1;
  		vv.push_back(x);  		
}
	}else dfs(nd,o,dis+1);	
  }
}
void dp(int o,int fa)
{
	int i;
	f[o][1]=a[o];
	for(i=0;i<v[o].size();i++)
	{
		int nd=v[o][i];
		if(h[nd]||nd==fa)continue;
		dp(nd,o);
		f[o][0]+=max(f[nd][0],f[nd][1]);
		f[o][1]+=f[nd][0];		
	}
}

int main()
{
	int i;
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		scanf("%lld",&x);
		v[x].push_back(i);
		v[i].push_back(x);		
	}
	for(i=1;i<=n;i++)
	{
		if(vis[i])continue;
	    vv.clear();
	    yici=0;
		dfs(i,0,1);
		if(vv.size()==0)
		{
		dp(i,0);
		ans+=max(f[i][1],f[i][0]);
	    }
		else 
		{
			for(int k=0;k<vv.size();k++)
		dp(vv[k],0);
			//第一个不取
			ll lin=0; 
			lin+=f[vv[0]][0];
				g[vv[vv.size()-1]][0]=f[vv[vv.size()-1]][0];
				g[vv[vv.size()-1]][1]=f[vv[vv.size()-1]][1];
			for(j=vv.size()-2;j>0;j--)
			{int o=vv[j],x=vv[j+1];
				g[o][0]=f[o][0];
				g[o][1]=f[o][1];
				g[o][0]+=max(g[x][0],g[x][1]);
				g[o][1]+=g[x][0];					
			}
			lin+=max(g[vv[1]][1],g[vv[1]][0]);
			//第一个取 
				ll lin2=0; 
			lin2+=f[vv[0]][1];
				g[vv[vv.size()-1]][0]=f[vv[vv.size()-1]][0];
				g[vv[vv.size()-1]][1]=0;
			for(j=vv.size()-2;j>0;j--)
			{int o=vv[j],x=vv[j+1];
				g[o][0]=f[o][0];
				g[o][1]=f[o][1];
				g[o][0]+=max(g[x][0],g[x][1]);
				g[o][1]+=g[x][0];					
			}
			lin2+=g[vv[1]][0];
			ans+=max(lin,lin2);
		}	
	}
	printf("%lld",ans);
}

    原文作者:骑士周游问题
    原文地址: https://blog.csdn.net/haobang866/article/details/77885510
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞