P1963 [NOI2009] 变换序列(匈牙利)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1963 [NOI2009] 变换序列(匈牙利)相关的知识,希望对你有一定的参考价值。

P1963 [NOI2009] 变换序列(匈牙利)

构造一个字典序最小的全排 p p p(0开始) 满足 m i n ( ∣ i − p i ∣ , n − ∣ i − p i ∣ ) = a i min(|i-p_i|,n-|i-p_i|)=a_i min(ipi,nipi)=ai

可以转化为二分图匹配问题。

关键如何求字典序最求,我们知道匈牙利是能换则换,所以我们考虑倒着匹配,这样前面就可以用字典序小的换掉字典序大的。

// Problem: P1963 [NOI2009] 变换序列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1963
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-11-07 16:18:17
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e4+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
const int hashmod[4] = {402653189,805306457,1610612741,998244353};
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define x first
#define y second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ios ios::sync_with_stdio(false),cin.tie(nullptr) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int mh[N],vis[N],n,ans[N];
int e[N][2],dep;
bool find(int x){
	for(int i=0;i<2;i++){
		int u=e[x][i];
		if(vis[u]==dep) continue;
			vis[u]=dep;
			if(mh[u]==-1||find(mh[u])){
				mh[u]=x,ans[x]=u;
				return true;
			}
	}
	return false;
}
int main(){
	scanf("%d",&n);
	mst(mh,-1);
	for(int i=0;i<n;i++){
		int x;scanf("%d",&x);
		e[i][0]=(i-x+n)%n,e[i][1]=(x+i)%n;
		if(e[i][0]>e[i][1]) swap(e[i][0],e[i][1]);
	}
	int c=0;
	for(int i=n-1;~i;i--){
		++dep;
		if(find(i)) c++;
	}
	if(c!=n) return puts("No Answer"),0;
	for(int i=0;i<n-1;i++) printf("%d ",ans[i]);
	printf("%d\\n",ans[n-1]);
	return 0;
}

以上是关于P1963 [NOI2009] 变换序列(匈牙利)的主要内容,如果未能解决你的问题,请参考以下文章

[NOI2009]变换序列

[luoguP1963] [NOI2009]变换序列(二分图最大匹配)

noi2009变换序列

BZOJ1562: [NOI2009]变换序列

bzoj1562 NOI2009—变换序列

bzoj1562: [NOI2009]变换序列