思路求hack
查看原帖
思路求hack
421265
eastcloud楼主2022/12/3 15:29

rt,我的想是对于每颗基环树,求出环上每个节点不经过其他环上节点的 dp 值,然后再在环上用环形 dp,dp 两次的方法处理。

但是题解里都是断边然后对于边的两端分别树形 dp,而我的做法只能拿 40 pts,代码应该没错,想问问思路错在哪里。

我的代码,应该还挺好懂的

// Problem: P2607 [ZJOI2008] 骑士
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2607
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
vector<ll> l[1000001];
vector<ll> g[1000001];
ll val[1000001],fa[1000001];
ll vis[1000001];
ll lop[1000001],dp[1000001][2];
ll dp2[1000001][2],dfn[1000001];
ll tr[1000001];
ll tot,all,num;
void dfs(ll x,ll f){
	fa[x]=f;dfn[x]=++all;vis[x]=vis[f];
	for(ll i=0;i<l[x].size();i++){
		ll v=l[x][i];
		if(v==f) continue;
		if(!dfn[v]) dfs(v,x);
		else{
			if(dfn[v]<dfn[x]) continue;
			g[vis[x]].push_back(v);
			for(ll j=fa[v];j!=x;j=fa[j])g[vis[x]].push_back(j);
			g[vis[x]].push_back(x);
		}
	}
}
void dfs2(ll x,ll f){
	dp[x][1]=val[x];
	for(ll i=0;i<l[x].size();i++){
		ll v=l[x][i];
		if(v==f || lop[v]) continue;
		dfs2(v,x);
		dp[x][1]+=dp[v][0];
		dp[x][0]+=max(dp[v][1],dp[v][0]);
	}
}
ll calc(ll bel){
	dp2[0][1]=dp[g[bel][0]][1];
	ll ans=0;
	for(ll i=1;i<g[bel].size();i++){
		dp2[i][1]=dp[g[bel][i]][1]+dp2[i-1][0];
		dp2[i][0]=max(dp2[i-1][1],dp2[i-1][0])+dp[g[bel][i]][0];
	}
	ans=max(ans,dp2[g[bel].size()-1][0]);
	dp2[0][1]=0;
	for(ll i=1;i<g[bel].size();i++){
		dp2[i][1]=dp[g[bel][i]][1]+dp2[i-1][0];
		dp2[i][0]=max(dp2[i-1][1],dp2[i-1][0])+dp[g[bel][i]][0];
	}
	ans=max(ans,max(dp2[g[bel].size()-1][0],dp2[g[bel].size()-1][1]));
	return ans;
}
int main(){
	ll n,v;
	cin>>n;
	for(ll i=1;i<=n;i++){
		cin>>val[i]>>v;
		l[i].push_back(v);
		l[v].push_back(i);
	}
	for(ll i=1;i<=n;i++){
		if(!dfn[i]){
			vis[0]=++num;
			tr[num]=i;
			dfs(i,0);
		}
	}
	for(ll i=1;i<=num;i++)for(ll j=0;j<g[i].size();j++)lop[g[i][j]]++;
	ll ans=0;
	for(ll i=1;i<=num;i++){
		if(!g[i].size()){
			dfs2(tr[i],0);
			ans+=max(dp[tr[i]][0],dp[tr[i]][1]);
		}
		for(ll j=0;j<g[i].size();j++)dfs2(g[i][j],0);
	}
	for(ll i=1;i<=num;i++)ans+=calc(i);
	cout<<ans;
}
2022/12/3 15:29
加载中...