P2607 [ZJOI2008] 骑士 我在做这道题的时候想到了与题解不同一种解法
在遇到环的时候多开一个dp2数组,单独处理带环的子树(不选择与根节点冲突的),在出环时把dp2合并进原来的dp数组,但是没过。TAT
请问这种做法是否可行,如果不可行,有没有巨佬可以帮我解释一下,谢谢!
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1*1e6+100;
vector <int>e[N];
int dp[N][2];
int dp2[N][2];
int h[N];
int vis[N];
int v[N];
int n;
void pre(int p){
vis[p]=1;
for(int k:e[p]){
if(vis[k]){
h[p]=1;
}
else pre(k),h[p]+=h[k];
}
}
int dfs(int p,int fa){
dp[p][1]=dp2[p][1]=v[p];
vis[p]=1;
int ret=0;
if(!h[fa] and h[p]) ret=2;
for(int k:e[p]){
if(vis[k]){
ret=1;
}
else{
if(dfs(k,p)){
dp2[p][0]+=dp[k][0];
dp2[p][1]+=dp[k][0];
}
else if(h[p] and ret!=2){
dp2[p][0]+=max(dp2[k][1],dp2[k][0]);
dp2[p][1]+=dp2[k][0];
}
if(ret==2){
dp[p][0]+=max(dp[k][1],dp[k][0]);
dp[p][1]+=dp2[k][0];
}
else{
dp[p][0]+=max(dp[k][1],dp[k][0]);
dp[p][1]+=dp[k][0];
}
}
}
if(!h[p]){
dp2[p][0]=dp[p][0];
dp2[p][1]=dp[p][1];
}
return ret;
}
int cd[N];
int rd[N];
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
int t1,t2;
cin>>t1>>t2;
v[i]=t1;
e[t2].push_back(i);
cd[t2]++;
rd[i]++;
}
for(int i=1;i<=n;i++){
if(!vis[i]) pre(i);
}
int ans=0;
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){
if(h[i]==1 and !vis[i]){
dfs(i,0);
ans+=max(dp[i][1],dp[i][0]);
}
}
cout<<ans<<endl;
}