提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
题意
有n个人 每个人都有自己想送礼物的人 每人只能收到一个礼物 不能送给自己 每个人都要收到礼物 安排一下 使得满足 送到自己的想要送的人的人数最大化提示:以下是本篇文章正文内容,下面案例可供参考
1.AC代码
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f3f;
const ll mod = 3221225473;
const int maxn = 1e5 + 1;
void solve()
{
int n,tot=0;
cin >> n;
vector<ll> pos(n+1),a(n+1); // a是记录人们想要送的 pos是记录送此位置的谁
vector<bool>used(n + 1), vis(n + 1); // used 记录有没有被送过 vis 记录有没有送过人
set<ll>s;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
s.insert(i);
}
for (int i = 1; i <= n; i++)
{
if (!used[a[i]])
{
used[a[i]] = vis[i] = 1;
tot++;
s.erase(a[i]);
pos[a[i]] = i;
}
}
for (int i = 1; i <= n; i++)
{
if (!vis[i])
{
auto it = s.begin();
if (*it != i)
{
a[i] = *it;
used[a[i]] = 1;
vis[i] = 1;
pos[a[i]] = i;
}
else
{
ll id = pos[a[i]];
a[i] = *it;
swap(a[i], a[id]);
pos[a[i]] = i, pos[a[id]] = id;
}
s.erase(it);
}
}
cout << tot << endl;
for (int i = 1; i <= n; i++)
cout << a[i] << " ";
cout << endl;
}
int main()
{
std::ios_base::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
做法总结
能够做到的使期望值达最大的数目刚好等于a中出现不重复数字的数量用s(set)来记录谁还没有被送过
然后 先开始遍历一遍
令 满足 !used[a[i]] 的人送礼物
然后遍历第二次
令 满足 !vis[i]的人送给 s里面 的人
此时会有两种情况
1.如果没送到 i 没关系
2. 如果送到了i 那么就把 i的礼物送给a[i] (这个一定被另一个人pos[a[i]]送了礼物)
令 pos[a[i]]送礼物给i 就可以解决这种情况啦