我们整个dp的思路就是 先找环 然后进行树形dp 把它看成某种意义的“缩点” 然后进行一个环上的dp
ZJOI 2008, 骑士
#include <bits/stdc++.h>
using namespace std;
#define int long long
//typedef long long ll;
typedef pair<int,int> pii;
#define x first
#define y second
#define pb push_back
#define inf 1e18
#define IOS std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fer(i,a,b) for(int i=a;i<=b;i++)
#define der(i,a,b) for(int i=a;i>=b;i--)
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0)putchar('-'),print(-x);if(x>9)print(x/10);putchar(x%10+'0');}
const int maxn=1e5+10;
const int mod=1e9+7;
int qmi(int a,int b)
{int res=1; while(b){ if(b&1) res=res*a%mod; a=a*a%mod; b>>=1; } return res;}
const int N=2e5+10;
int dr[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int n,k;
int a[N];
int vis[N];
vector<int>g[N];
int fa[N];
int onc[N];
int dp[N][2];
int ans;
int dp2[N][2];
void dfs(int u)
{
vis[u]=true;
dp[u][1]=a[u];
for(auto v:g[u])
{
if(onc[v])continue;
dfs(v);
dp[u][0]+=max(dp[v][0],dp[v][1]);
dp[u][1]+=dp[v][0];
}
}
void solve()
{
cin>>n;
fer(i,1,n)
{
cin>>a[i]>>fa[i];
g[fa[i]].pb(i);
}
fer(i,1,n)if(!vis[i])
{
int u=i;
while(!vis[u])
{
vis[u]=true;
u=fa[u];
}
int v=u;
vector<int>c;
while(true)
{
c.pb(v);
onc[v]=true;
v=fa[v];
if(v==u)break;
}
for(auto v:c)dfs(v);
int m=c.size();
int ans2=-inf;
fer(t,0,1)
{
fer(j,0,1)
{
if(j==t)dp2[0][j]=dp[c[0]][j];
else dp2[0][j]=-inf;
}
fer(i,1,m-1)
{
int u=c[i];
dp2[i][0]=max(dp2[i-1][0],dp2[i-1][1])+dp[u][0];
dp2[i][1]=dp2[i-1][0]+dp[u][1];
}
if(!t)ans2=max(ans2,max(dp2[m-1][0],dp2[m-1][1]));
else ans2=max(ans2,dp2[m-1][0]);
}
ans+=ans2;
}
cout<<ans<<endl;
}
signed main()
{
IOS;
int _=1;
//cin>>_;
while(_--) solve();
return 0;
}