每个人到他认为最强的人连一条边。
缩点后,入度为0的点是最小解,强联通分量是最大解。
---
const int maxn=111100;
const int maxm=210000;
int n;
struct Node {
int to,next;
} edges[maxm];
int head[maxn],edge;
void addedge(int u,int v) {
edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
}
void prepare() {
memset(head,-1,sizeof head);
edge=0;
}
int a[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],scc_cnt,dfs_clock;
stack<int>stk;
void dfs(int u) {
pre[u]=lowlink[u]=++dfs_clock;
stk.push(u);
for (int i=head[u]; i!=-1; i=edges[i].next) {
int v=edges[i].to;
if (!pre[v]) {
dfs(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
} else if (!sccno[v]) {
lowlink[u]=min(lowlink[u],pre[v]);
}
}
if (lowlink[u]==pre[u]) {
scc_cnt++;
int x;
do {
x=stk.top();
stk.pop();
sccno[x]=scc_cnt;
} while (x!=u);
}
}
void find_scc(int n) {
dfs_clock=scc_cnt=0;
clr(sccno,0);
clr(pre,0);
while (!stk.empty()) stk.pop();
REP_1(i,n) if (!pre[i]) dfs(i);
}
int num[maxn];
int main() {
memset(num,0,sizeof num);
scanf("%d",&n);
prepare();
for (int i=1; i<=n; i++) {
scanf("%d",&a[i]);
addedge(i,a[i]);
}
find_scc(n);
for (int i=1; i<=n; i++) {
if (sccno[i]!=sccno[a[i]]) {
num[sccno[a[i]]]++;
}
}
int cnt=0;
for (int i=0; i<scc_cnt; i++) {
if (num[i]==0) cnt++;
}
printf("%d %d\n",cnt,scc_cnt);
return 0;
}
---