题意 :
给定一个长度为 N 的序列 A,使得每个 A[i] 都满足 1≤A[i]≤N。
Takahashi 和 Aoki 将玩 N 轮游戏。
对于每一轮游戏,Aoki 会指定一个正整数 Ki,然后 Takahashi 会选择一个整数 Si,在黑板上写下它,并重复进行 Ki 次以下操作:
将黑板上的数值 x 替换为 A[x]。 如果在第 Ki 次操作后黑板上写的是数字 i,则 Takahashi 获胜,否则 Aoki 获胜。
注意,对于每轮游戏,Takahashi 和 Aoki 都是为了自己获胜而采取最优策略。
思路分析:
对于每一个数字 i ,我们需要求出它是否可以让 T 获胜 。根据题意,可以发现是让我们把数字沿着值作为下标 再到 下一个值, 这样看就是一张单点出度为1 存在环的图。
对于每一轮的操作的数字 即为 i 。
对于T:T的目的是让 路径的目标点为 i,如果i 在一个环上则T 可以逆向找到距离目标点 i 有 Ki步的地方出发,这样T就必胜了。
对于 A: A的目标是让i不在终点,那就是说不让i出现在环上面。
综上 对所有在环上的点i,T必胜;不在环上的点,A必胜。
一想到环就可以用拓扑排序来处理,找到在环上的点,问题就解决了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 2e5 + 5;
const ll mod = 100003;
int a[M],d[M],n;
queue<int>q;
vector<int>v[M];
void topsort(){
for(int i=1;i<=n;i++)if(!d[i])q.push(i);
while (!q.empty()){
int x=q.front();
q.pop();
for(auto y:v[x]){
if(--d[y]==0)q.push(y);
}
}
return ;
}
void solve()
{
cin>>n;int res=0;
for(int i=1;i<=n;i++){
cin>>a[i];
v[i].push_back(a[i]);
d[a[i]]++;
}
topsort();
for(int i=1;i<=n;i++){
if(d[i])res++;
}
cout<<res<<endl;
return ;
}
int main()
{
int t = 1;
// cin >> t;
while (t--)
{
solve();
}
return 0;
}