题目大意:
有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。
思路:
首先考虑最小,叶子结点杀的人必定会死,那么它就不要再杀人了,直接将他干掉。不断地从叶子结点入手,最后只会剩下一些环,环上的答案即
⌈
s
i
z
e
2
⌉
\lceil \frac{size}{2}\rceil
⌈2size⌉。
考虑最大,叶子结点必定会活下来,一个环套树除了叶子结点都会死光,一个单纯的环(除了自环)最多死
s
i
z
e
−
1
size-1
size−1个人。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
typedef long long ll;
using namespace std;
void File(){
freopen("bzoj1124.in","r",stdin);
freopen("bzoj1124.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=1e6+10;
int n,to[maxn];
namespace GetMin{
bool die[maxn],vis[maxn];
int deg[maxn],sum,fa[maxn],sz[maxn];
queue<int>qu;
int find(int x){return fa[x]==x ? x : fa[x]=find(fa[x]);}
void solve(){
REP(i,1,n)++deg[to[i]];
REP(i,1,n)if(!deg[i])qu.push(i);
while(!qu.empty()){
int u=qu.front();
qu.pop(); vis[u]=1;
if(!die[to[u]]){
vis[to[u]]=1; die[to[u]]=1;
if(!die[to[to[u]]]){
--deg[to[to[u]]];
if(!deg[to[to[u]]])
qu.push(to[to[u]]);
}
}
}
REP(i,1,n)sum+=die[i],fa[i]=i,sz[i]=1;
REP(i,1,n)if(!vis[i]){
int fx=find(i),fy=find(to[i]);
if(fx!=fy){
fa[fx]=fy;
sz[fy]+=sz[fx];
}
}
REP(i,1,n)if(!vis[find(i)]){
vis[find(i)]=1;
sum+=(sz[find(i)]-1)/2+1;
}
}
}
namespace GetMax{
//所有的叶子结点都可以活下来。
//如果只有单纯的环(除了自环),环上可以存活一个人。
int deg[maxn],sum,fa[maxn],sz[maxn];
bool tag[maxn],vis[maxn];
int find(int x){return fa[x]==x ? x : fa[x]=find(fa[x]);}
void solve(){
sum=n;
REP(i,1,n)++deg[to[i]],fa[i]=i,sz[i]=1;
REP(i,1,n)if(!deg[i])--sum;
REP(i,1,n){
int fx=find(i),fy=find(to[i]);
if(fx!=fy){
fa[fx]=fy;
sz[fy]+=sz[fx];
}
}
REP(i,1,n)if(deg[i]>=2)tag[find(i)]=1;
REP(i,1,n)if(!vis[find(i)] && !tag[find(i)] && to[find(i)]!=find(i))
vis[find(i)]=1,--sum;
}
}
int main(){
File();
read(n);
REP(i,1,n)read(to[i]);
GetMin::solve();
GetMax::solve();
printf("%d %d\n",GetMin::sum,GetMax::sum);
return 0;
}