环套树DP……每个点要是被选了儿子里必须有没被选的
对于树上部分,f[i][j]表示i节点,状态为j的时候子树内的答案
状态有三种:没被选,被选了,被选了但是根节点目前还没有人限制他(即根节点不在环上的儿子里没有没被选的)
然后把环拆成链,强制另第一个不选或第一个选但不是最后一个限制他或第一个选并且是最后一个限制他
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 1000010
#define MAXM 1010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
struct vec{
int to;
int fro;
};
vec mp[MAXN];
int tai[MAXN],cnt;
int n;
int f[MAXN][3],fa[MAXN],t[MAXN];
int F[MAXN][2];
bool dpd[MAXN];
int vis[MAXN];
int tot,T;
int ans;
inline void be(int x,int y){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
}
void dfs(int x){
int i,y;
bool flag=0;
int sum=0,tmp=INF;
dpd[x]=1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(y!=fa[x]&&vis[y]!=T){
flag=1;
dfs(y);
sum+=max(f[y][0],f[y][1]);
if(f[y][0]>=f[y][1]){
tmp=0;
}else{
tmp=min(tmp,f[y][1]-f[y][0]);
}
}
}
f[x][0]=sum;
f[x][1]=sum-tmp+1;
f[x][2]=sum+1;
}
int dp(){
int i;
int re=0;
F[1][0]=f[t[1]][0];
F[1][1]=-INF;
for(i=2;i<=tot;i++){
F[i][0]=f[t[i]][0]+max(F[i-1][0],F[i-1][1]);
F[i][1]=max(f[t[i]][1]+max(F[i-1][0],F[i-1][1]),f[t[i]][2]+F[i-1][0]);
}
re=max(F[tot][0],F[tot][1]);
F[1][0]=-INF;
F[1][1]=f[t[1]][1];
for(i=2;i<=tot;i++){
F[i][0]=f[t[i]][0]+max(F[i-1][0],F[i-1][1]);
F[i][1]=max(f[t[i]][1]+max(F[i-1][0],F[i-1][1]),f[t[i]][2]+F[i-1][0]);
}
re=max(re,F[tot][1]);
F[1][0]=-INF;
F[1][1]=f[t[1]][2];
for(i=2;i<=tot;i++){
F[i][0]=f[t[i]][0]+max(F[i-1][0],F[i-1][1]);
F[i][1]=max(f[t[i]][1]+max(F[i-1][0],F[i-1][1]),f[t[i]][2]+F[i-1][0]);
}
re=max(re,F[tot][0]);
return re;
}
int main(){
/*
freopen("data.txt","r",stdin);
freopen("dui.txt","w",stdout);
//*/
int i,x;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&fa[i]);
be(fa[i],i);
}
for(i=1;i<=n;i++){
if(!dpd[i]){
x=i;
T++;
while(vis[x]!=T){
vis[x]=T;
x=fa[x];
}
T++;
while(vis[x]!=T){
vis[x]=T;
x=fa[x];
}
while(!dpd[x]){
dfs(x);
x=fa[x];
}
tot=0;
T++;
while(vis[x]!=T){
vis[x]=T;
t[++tot]=x;
x=fa[x];
}
ans+=dp();
}
}
printf("%d\n",ans);
return 0;
}
/*
6
5 3 2 3 2 1
*/