描述
题解
一开始打算反向建图,后来发现多此一举,甚至可能更加麻烦,所以还是正向建图,不过这里的图比较特殊,建好后包括三种结构——链、环、集中(我瞎叫的,就是一个点连着多条链,链方向都指向中心点)。其实这三种结构可以归为两种,链和环,只要把第三种结构拆分为数条链就好了。接着进行遍历,先处理链状结构,然后处理环状结构,最后分别统计各个结构对结果的贡献,累加即可。至于这个贡献,和链或者环的长度有关,具体的还要考虑奇偶性。GG~~~一道水题。
代码
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 1e6 + 10;
int pre[MAXN]; // 前驱的数目
int net[MAXN];
int vis[MAXN];
int main(int argc, const char * argv[])
{
int K;
cin >> K;
int N;
while (K--)
{
memset(pre, 0, sizeof(pre));
memset(vis, 0, sizeof(vis));
memset(net, -1, sizeof(net));
cin >> N;
int a;
for (int i = 1; i <= N; i++)
{
cin >> a;
pre[a]++;
net[i] = a;
}
int res = 0;
for (int i = 1; i <= N; i++)
{
if (pre[i] == 0)
{
int len = 0;
int nt = i;
while (nt != -1 && vis[nt] == 0)
{
vis[nt] = 1;
len++;
nt = net[nt];
}
res += len / 2;
if (len & 1)
{
res++;
}
}
}
for (int i = 1; i <= N; i++)
{
if (vis[i] == 0)
{
int len = 0;
int nt = i;
while (vis[nt] == 0)
{
vis[nt] = 1;
len++;
nt = net[nt];
}
res += len / 2;
if (len & 1)
{
res++;
}
}
}
cout << N - res << '\n';
}
return 0;
}