Problem - 1530D - Codeforces
每年12月,VK都会为其员工举办名为 "秘密圣诞老人 "的传统活动。它是这样发生的。
从1到n的n名员工参加了这个活动。每个员工i被分配到一个不同的员工bi,员工i必须给这个员工做一份新年礼物。每个员工正好被分配给另外一个员工,没有人被分配给自己(但两个员工可能被分配给对方)。从形式上看,所有bi必须是1到n之间的不同整数,对于任何i,bi≠i必须成立。
该分配通常是随机产生的。今年,作为一个实验,所有活动参与者都被问及他们希望向谁赠送礼物。每个员工i都说他们希望给员工ai送礼。
找到一个有效的分配b,使员工的愿望得到满足的数量最大化。
输入
每个测试包含多个测试案例。第一行包含测试用例的数量t(1≤t≤105)。测试用例的描述如下。
每个测试用例由两行组成。第一行包含一个整数n(2≤n≤2⋅105)--事件参与者的数量。
第二行包含n个整数a1,a2,...,an (1≤ai≤n; ai≠i) --雇员的愿望,从1到n依次排列。
保证所有测试案例的n之和不超过2⋅105。
输出
对于每个测试案例,打印两行。
在第一行,打印一个整数k(0≤k≤n)--在你的任务中实现的愿望的数量。
在第二行,打印n个不同的整数b1,b2,...,bn(1≤bi≤n;bi≠i)--分配给雇员1,2,...,n的雇员数。
k必须等于i的值的数量,使ai=bi,而且必须尽可能大。如果有多个答案,打印任何一个。
例子
输入复制
2
3
2 1 2
7
6 4 6 2 4 5 6
输出拷贝
2
3 1 2
4
6 4 7 2 3 5 1
注意
在第一个测试案例中,存在两个有效的赋值。[3,1,2]和[2,3,1]。前者满足了两个愿望,而后者只满足了一个。因此,k=2,唯一正确的答案是[3,1,2]。
题解:
根据题意,我们尽量让多的人可以送给想要的人
对于没有送礼物的,送给没有收到礼物的人
这样下去可能会有,自己送给自己的情况,我们记录下来,并且找到之前一样想送给相同人的人
交换他们俩,想送的情况,最优情况并不会改变,如上图
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
using namespace std;
#define int long long
int a[200050];
int b[200050];
int d[200050];
int c[200050];
int e[200050];
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
{
c[i] = b[i] = 0;
}
for(int i = 1;i <= n;i++)
{
cin >> a[i];
c[a[i]] = 1;
}
int s = 0;
for(int i = 1;i <= n;i++)
{
if(c[i])
s++;
}
cout << s<<'\n';
for(int i = 1;i <= n;i++)
{
if(c[a[i]])
{
c[a[i]] = 0;
d[i] = a[i];
b[a[i]] = 1;
}
else
{
d[i] = 0;
}
}
for(int i = 1,j = 1;i <= n;i++)
{
if(!d[i])
{
while(b[j])
{
j++;
}
d[i] = j++;
}
}
for(int i = 1;i <= n;i++)
e[d[i]] = i;
for(int i = 1;i <= n;i++)
{
if(d[i] == i)
{
swap(d[i],d[e[a[i]]]);
}
}
for(int i = 1;i <= n;i++)
cout <<d[i]<<" ";
cout <<"\n";
}
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}