Official

E - Transition Game Editorial by en_translator


Let \(S\) be a set of all ntegers between \(1\) and \(N\) (note that \(S\) is defined differently from the Problem Statement), and define a map \(f\) from \(S\) to \(S\) by \(f(x)=A_x\).

Moreover, define a sequence of sets \(S_0,S_1,\ldots\) by \(S_0=S\) and \(S_i=f(S_{i-1})\) (i.e. \(S_i=\{f(x)|x\in S_{i-1} \}\)) for all \(1\leq i\). Then, in the original Problem Statement, Takahashi wins the game if and only if \(x\in S_k\) for all positive integers \(k\).

Now, for the sequence \(S_0,S_1,\ldots\), we have \(S_0\supseteq S_1\); by definition, if \(S_{i-1}\supseteq S_i\) then \(S_i\supseteq S_{i+1}\); so \(S_0\supseteq S_1\supseteq S_2\cdots\) by induction.
Since \(|S_0|=N\), \(S_i\) is a finite set. Noting that \(|S_i|-1\geq |S{i+1}|\) if \(S_i\supsetneq S_{i+1}\), and that \(|S_i|>0\) for all \(i\) by definition, there exists \(0\leq i_0\leq N-1\) such that \(S_{i_0}=S_{i_0+1}\).
Here, by definition of \(S_i\), if \(S_{i}=S_{i+1}\) then \(S_{i+1}=S_{i+2}\), so \(S_{i_0}=S_{i_0+1}=S_{i_0+2}=\cdots\) by induction.
Thus, once we find such \(i_0\) and \(S_{i_0}\), the answer is the size of \(S_{i_0}\).

There are several ways to find this. For example, we can manage the number \(c_{i,y}\) of elements \(x\) in \(S_i\) such that \(f(x)=y\) for each \(0\leq i\) and \(1\leq y\leq N\).
\(c_{0,y}\) can be easily found as the number of \(y\) such that \(A_x=y\).
Here, \(y\) is contained in \(S_1\) if and only if \(c_{0,y}>0\) by definition.
Next, we try to find \(c_{1,y}\). Considering the difference b\(d_{1,y}\)etween \(c_{0,y}\) and \(c_{1,y}\), denoting by \(d_{1,y}\) the number of \(x\in(S_0\backslash S_1)\) such that \(f(x)=y\), we have \(c_{1,y}=c_{0,y}-d_{1,y}\).
\(y\) is contained in \(S_2\) if and only if \(c_{1,y}>0\), and the same applies over and over again.

A naive implementation of this algorithm costs \(\Theta(N^2)\) time; however, we can reuse the array \(c_{i,y}\) and, instead of finding \(d_{i,y}\) and subtracting it, decrement the value \(c_{i,f(x)}\) for each \(x\in(S_i\backslash S_{i+1})\) to get the same effect. Also, the only possible elements of \((S_i\backslash S_{i+1})\) are those on which the decrement was done in the step above, so they are done at most \(N\) times in total. Therefore, it can be computed in a total of \(O(N)\) time, and the problem has been solved fast enough.

Actually, you don’t need to distinguish by \(i\); you can first push to a queue those with \(c_y\) being \(0\), decrement \(c_{f(x)}\) for each element \(x\) of the queue, and add those such that \(c_{f(x)}=0\) to the queue. This can be understood by considering the directed graph with \(N\) vertices and \(N\) edges, where edges go from vertices \(i\) to vertices \(A_i\).

Sample code in C++:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < n; ++i)

int main(void){
	int n,sz;
	cin>>n;
	vector<int>a(n),c(n);
	vector<vector<int> >b(n);
	int ans=n;
	rep(i,n){
		cin>>a[i];
		a[i]--,c[a[i]]++;
	}
	rep(i,n)if(c[i]==0){
		ans--;
		b[0].push_back(i);
	}
	rep(i,n-1){
		sz=b[i].size();
		if(sz==0)break;
		rep(j,sz){
			c[a[b[i][j]]]--;
			if(c[a[b[i][j]]]==0)ans--,b[i+1].push_back(a[b[i][j]]);
		}
	}
    cout<<ans<<endl;
	return 0;
}

posted:
last update: