BZOJ 1562 变换序列 二分图匹配+字典序

时间:2024-10-12 19:34:49

题目链接:

https://www.lydsy.com/JudgeOnline/problem.php?id=1562

题目大意:

BZOJ 1562 变换序列 二分图匹配+字典序

思路:

逆序匹配,加边匹配的时候保持字典序小的先加入。

具体证明:https://www.byvoid.com/zhs/blog/noi-2009-transform

 #include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Mem(a) memset(a, 0, sizeof(a))
#define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
#define MID(l, r) ((l) + ((r) - (l)) / 2)
#define lson ((o)<<1)
#define rson ((o)<<1|1)
#define Accepted 0
#pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} typedef long long ll;
const int maxn = + ;
const int MOD = ;//const引用更快,宏定义也更快
const int INF = 1e9 + ;
const double eps = 1e-; int n, m;
vector<int>Map[maxn];
int cx[maxn], cy[maxn];
bool vis[maxn];
//cx[i]表示X部i点匹配的Y部顶点的编号
//cy[i]表示Y部i点匹配的X部顶点的编号 bool dfs(int u)//dfs进入的都是X部的点
{
for(int i = ; i < Map[u].size(); i++)//枚举Y部的点,判断X部的u和Y部的v是否存在路径
{
int v = Map[u][i];
//如果存在路径并且还没被标记加入增广路
if(!vis[v])//vis数组只标记Y组
{
vis[v] = ;//标记加入增广路 //如果Y部的点v还未被匹配
//或者已经被匹配了,但是可以从v点原来匹配的cy[v]找到一条增广路
//说明这条路就可是一个正确的匹配
if(cy[v] == - || dfs(cy[v]))
{
cx[u] = v;//可以匹配,进行匹配
cy[v] = u;
return ;
}
}
}
return ;//不能匹配
}
int maxmatch()//匈牙利算法主函数
{
int ans = ;
memset(cx, -, sizeof(cx));
memset(cy, -, sizeof(cy));
for(int i = n - ; i >= ; i--)//逆序匹配 保证最优解
{
if(cx[i] == -)//如果X部的i还未匹配
{
memset(vis, , sizeof(vis));//每次找增广路的时候清空vis
ans += dfs(i);
}
}
return ans;
}
int main()
{
IOS;
cin >> n;
int x, ti;
for(int i = ; i < n; i++)
{
cin >> x;
//abs(i - ti) = x => ti = i - x or i + x
//abs(i - ti) = n - x; => ti = i - (n - x) or i + n - x
//等价于ti = (i - x + n) % n or (i + x) % n;
int u = (i - x + n) % n;
int v = (i + x) % n;
if(u > v)swap(u, v);//保证字典序小的在前面
Map[i].push_back(u);
Map[i].push_back(v);
}/*
for(int i = 0; i < n; i++)
{
cout<<i<<" : ";
for(int j = 0; j < Map[i].size(); j++)cout<<Map[i][j]<<" ";
cout<<endl;
}*/
if(maxmatch() != n)cout<<"No Answer\n";
else
{
cout<<cx[];
for(int i = ; i < n; i++)cout<<" "<<cx[i];
cout<<"\n";
}
return Accepted;
}