首先n点n边,是一个基环树,
可以观察得到其实最大值是不变的
剩下的人自己随便找个人匹配即可
所以关键是构造一个方案解决匹配到自己的情况
找到所有没送出礼物的人,然后直接匹配,如果匹配到自己
因为没有送出礼物的人想送出礼物的人被选了,才没送出
所以可以换一下,让当前这个没送出礼物的人送给想送出礼物的目标,然后让原本送给目标的人怂给当前这个没有送出礼物的人即可
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int n,m;
vector<int> g[N];
int a[N];
int vis[N],mach[N];
void solve()
{cin>>n;for(int i=1;i<=n;i++){cin>>a[i];vis[i]=0;mach[i]=0;}int ans=0;for(int i=1;i<=n;i++){if(vis[a[i]]) continue;vis[a[i]]=i;mach[i]=a[i];ans++;}cout<<ans<<"\n";vector<int> res;for(int i=1;i<=n;i++){if(vis[i]==0) res.push_back(i);}int p=1;//mach第i个人喜欢的那个人 vis a[i]选的人的编号for(auto it:res){while(mach[p]) p++;//mach[p]=it;if(p==it){swap(mach[p],mach[vis[a[p]]]);vis[a[p]]=p;}}for(int i=1;i<=n;i++){cout<<mach[i]<<" ";}cout<<"\n";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}