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(∣i−pi∣,n−∣i−pi∣)=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] 变换序列(匈牙利)的主要内容,如果未能解决你的问题,请参考以下文章