题意:
把强连通缩点,然后求有几个点。再求有一个叶子。这个图不一定联通。 英语4级低空飘过的人,看不懂题啊。。。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
using namespace std;
const int N = 100009;
vector<int> L1[N],L2[N];
int n;
int col[N],ind,color,dfn[N],low[N],post[N];
stack<int> S;
void tarjan(int k)
{
//cout<<k<<endl;
dfn[k] = low[k] = ind++;
post[k] = 1;
S.push(k);
for(int i=0;i<L1[k].size();i++)
{
int to = L1[k][i];
if(!dfn[to])
{
tarjan(to);
low[k] = min(low[to],low[k]);
}else
{
if(post[to]&&low[k]>dfn[to])
low[k] = dfn[to];
}
}
if(dfn[k]==low[k])
{
int i;color++;
for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop())
{
col[i] = color;
post[i] = 0;
}
col[k] = color;post[k] = 0;
}
}
int visit[N];
int ans1;
void dfs(int k,int f)
{
visit[k] = 1;
int a = 0;
for(int i=0;i<L2[k].size();i++)
{
int to = L2[k][i];
if(to==f||visit[to]) continue;
dfs(to,k);
a++;
}
if(a==0)
{
ans1++;
}
}
void solve()
{
memset(dfn,0,sizeof(dfn));
ind = 1;color=0;
int a,b;
tarjan(0);
for(int i=0;i<=n;i++)
for(int j=0;j<L1[i].size();j++)
{
a = col[i];b = col[L1[i][j]];
L2[a].push_back(b);
}
dfs(col[0],-1);
printf("%d %d\n",ans1,color-1);
}
int v[N],in[N];
void ddfs(int k)
{
if(in[k]) return ;
in[k] = 1;
for(int i=0;i<L1[k].size();i++)
ddfs(L1[k][i]);
}
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d",&n);
int a;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
if(a==i) continue;
L1[i].push_back(a);
v[a] = 1;
}
for(int i=1;i<=n;i++)
if(!v[i]) L1[0].push_back(i),ddfs(i);
for(int i=1;i<=n;i++)
if(!in[i]) L1[0].push_back(i),ddfs(i);
solve();
return 0;
}