1. 程式人生 > 其它 >Codeforces Round #733 D. Secret Santa(構造)

Codeforces Round #733 D. Secret Santa(構造)

題目連結

題意

就是自己不能收到自己的東西,儘量收到自己想要的禮物.

思路

儘量收到自己想要的比較好操作,直接就是看那些數字出現過,
然後難就難在剩下的分配,不能把自己的分配給自己.首先我們需要知道自己一定不會想要自己的這個後面有大用.
其次我們可以先固定一部分自己想要的.就是那些出現過的直接分配給對應的某一個人即可.剩下的就需要分配.我們先對其,順序分配(並不保證不會出現分配給自己禮物的現象).所以我們還需要進行下一步操作,就是藉助上面我們優先確定的那部分人手裡的禮物來改變自己分配給自己的現象'這樣交換,使得自己不把禮物送到自己手裡.

void solve()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		b[i]=c[i]=0;
	}
	ll sum=0;
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]),c[a[i]]=1;
	for(int i=1;i<=n;i++) if(c[i])++sum;
	cout<<sum<<endl;
	
	for(int i=1;i<=n;i++){
		if(c[a[i]]){
			d[i] = a[i];
			b[a[i]] = 1;///數字已經選了
			c[a[i]] = 0;
		}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[e[a[i]]],d[i]);///關鍵之處,神來之筆 ,借用原本我們確定不會出現矛盾的點來替代.
	}
	for(int i=1;i<=n;i++) cout<<d[i]<<" ";
	cout<<endl;
}