题解:P10933 创世纪
思路
本题如果将
考虑某一棵基环树:
先找到环上的一点
但其中
然后,因为这是忽略了
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int bid,h[N],nxt[N],to[N],n,a[N],f[N][2],ans,km;
bool vis[N];
void add(int x,int y){
to[++bid]=y;
nxt[bid]=h[x];
h[x]=bid;
}
int dp(int x,int d){
f[x][0]=f[x][1]=0;
vis[x]=1;
int res=0,c=1e9+7;
for(int i=h[x];i;i=nxt[i]){
int y=to[i];
if(y==km)continue;
res=dp(y,d);
c=min(c,res-f[y][0]);
f[x][0]+=res;
}
f[x][1]=f[x][0]-c+1;
if(d&&x==a[km])f[x][1]+=c;
return max(f[x][0],f[x][1]);
}
int hjw(int x){
for(km=x;!vis[a[km]];vis[km]=1)km=a[km];
int cnt=dp(km,0);
dp(km,1);
return max(cnt,f[km][0]);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
add(a[i],i);
}
for(int i=1;i<=n;i++)if(!vis[i])ans+=hjw(i);
cout<<ans;
return 0;
}