#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000005
#define INF 1000000000
using namespace std;
struct Edge {
int from,to,nxt;
Edge() {}
Edge(int _from,int _to,int _nxt):
from(_from),to(_to),nxt(_nxt) {}
}e[N];
int n,tot,ans,mark,root,fir[N],a[N],f[N],g[N],pa[N];
bool vis[N];
void Add_Edge(int from,int to) {
e[++tot]=Edge(from,to,fir[from]), fir[from]=tot;
return ;
}
void dfs(int x) {
vis[x]=true;
if(vis[a[x]]) mark=x;
else dfs(a[x]);
return ;
}
void dp(int x) {
vis[x]=true;
f[x]=1, g[x]=INF;
if(x==root) g[x]=0;
for(int i=fir[x];~i;i=e[i].nxt) {
if(i==mark || e[i].to==pa[x]) continue;
pa[e[i].to]=x;
dp(e[i].to);
g[x]+=min(f[e[i].to],g[e[i].to]);
g[x]=min(g[x],f[x]+f[e[i].to]-1);
f[x]+=min(f[e[i].to],g[e[i].to]);
}
return ;
}
int main() {
memset(fir,-1,sizeof fir);
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",a+i), Add_Edge(a[i],i);
for(int i=1;i<=n;++i) {
if(vis[i]) continue;
dfs(i);
root=a[mark], dp(mark);
int tmp=f[mark];
root=0, dp(mark);
ans+=min(tmp,g[mark]);
}
printf("%d\n",n-ans);
return 0;
}
BZOJ 3037 创世纪 树形DP
最新推荐文章于 2019-09-20 19:54:00 发布