记录编号 421433 评测结果 AAAAAAAAAA
题目名称 膜法师 最终得分 100
用户昵称 Gravatarlicone 是否通过 通过
代码语言 C++ 运行时间 1.019 s
提交时间 2017-07-06 20:16:24 内存使用 44.19 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<queue>
using namespace std;

const int N=1000005;

int n,x,a[N],du[N],maxx,minn,c[N],cnt,num[N],num0[N],tot1,fi[N],w[N<<1],ne[N<<1],FI[N];
bool b[N],vis[N];

queue<int> q;

int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

void add(int u,int v)
{
	w[++cnt]=v;ne[cnt]=fi[u];fi[u]=cnt;du[u]++;
	w[++cnt]=u;ne[cnt]=fi[v];fi[v]=cnt;
}

void dfs(int u,int fa)
{
	c[u]=cnt;num[cnt]++;b[u]=1;
	for(int i=fi[u];i;i=ne[i])
	  if(!b[w[i]] && w[i]!=fa && w[i]!=u) dfs(w[i],u);
}

bool che(int u,int siz)
{
	int z=a[u],now=1;
	while(z!=u && now<siz) z=a[z],now++;
	return z==u && now==siz;
}

int main()
{
//	freopen("1.in","r",stdin);
//	freopen("1.out","w",stdout);
	freopen("maf.in","r",stdin);
	freopen("maf.out","w",stdout);
	int __size__= 128 << 20;
	char *__p__ = (char*)malloc(__size__) + __size__;
	__asm__("movl %0, %%esp\n" :: "r"(__p__));
	n=read();
	for(int i=1;i<=n;i++) a[i]=read(),add(a[i],i);cnt=0;
	for(int i=1;i<=n;i++) if(!b[i]) cnt++,dfs(i,0),FI[cnt]=i;
	for(int i=1;i<=n;i++) if(!du[i]) num0[c[i]]++;
	for(int i=1;i<=cnt;i++)
	  if(num[i]==1) maxx++;
	  else if(che(FI[i],num[i])) maxx+=num[i]-1;
	  else maxx+=num[i]-num0[i];
	for(int i=1;i<=n;i++) if(!du[i]) q.push(i);
	memset(b,0,sizeof(b));
	while(!q.empty())
	{
		int k=q.front();q.pop();vis[k]=1;k=a[k];
		if(vis[k]) continue;
		b[k]=vis[k]=1;minn++;
		du[a[k]]--;
		if(!du[a[k]]) q.push(a[k]);
	}
	for(int i=1;i<=n;i++)
	  if(!vis[i])
	  {
	  	x=i;tot1=0;
	  	while(!vis[x])
	  	{
	  		vis[x]=1;tot1++;x=a[x];
	  	}
	  	minn+=(tot1+1)/2;
	  }
	printf("%d %d\n",minn,maxx);
	return 0;
}