发现这是若干个基环内向树和若干个环
最坏情况下:
一个单独的环死剩1个
一个基环内向树死剩入度为0的点
最优情况下,显然按照拓扑序开枪死的人最少,模拟一下就行了
注意特判一个单独的自环qwq
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxn = 1100000;
int n,m;
int a[maxn],alive[maxn];
int d[maxn],ind[maxn];
queue<int>q;
int ans1,ans2;
bool v[maxn];
int flag,num;
void dfs(const int x)
{
if(v[x]) return ;
flag=max(flag,d[x]); num++;
v[x]=true;
int y=a[x];
if(alive[x]) alive[y]=0,ans1++;
dfs(y);
}
int main()
{
read(n);
for(int i=1;i<=n;i++) read(a[i]),ind[a[i]]++;
for(int i=1;i<=n;i++) alive[i]=1,d[i]=ind[i];
ans1=0; ans2=n;
for(int i=1;i<=n;i++) if(!ind[i])
ans2--,q.push(i);
while(!q.empty())
{
const int x=q.front(); q.pop();
int y=a[x];
if(alive[x])
{
if(alive[y]) alive[y]=0,ans1++;
if(ind[y]) ind[y]=0,q.push(y);
}
else
{
if(ind[y])
{
ind[y]--;
if(!ind[y]) q.push(y);
}
}
}
for(int i=1;i<=n;i++)
if(ind[i]&&!v[i])
{
flag=num=0; dfs(i);
if(flag==1&&num>1) ans2--;
}
printf("%d %d\n",ans1,ans2);
return 0;
}