[bzoj1562][NOI2009]变换序列
题目大意:有两个序列$a$和$b$,每个分别有$n(n\leqslant10^4)$个元素,序列$a$中的数为$0\sim n-1$的一个排列。$T_i$为$(a_i+b_i)\bmod n$或者$(a_i-b_i)\bmod n$。要求使得$\displaystyle\bigcup\limits_{i=1}^{n-1}T_i=\{0,1,\cdots,n-1\}$,输出$T_i$,如有多解,输出字典序最小的
题解:匈牙利算法,二分图完美匹配,每个$T_i$都有两种取值,可以倒着搜索,使得数字小的可以把数字大的挤掉,并且在枚举边的时候,从小到大搜索,就可以保证字典序最小,复杂度$O(n^2)$
卡点:1.最后 puts("\b") 锅了。。。。
C++ Code:
#include <cstdio> #include <cstring> #include <bitset> #define maxn 10010 int n, ans[maxn], res[maxn]; int e[maxn][2]; std::bitset<maxn> v; bool dfs(int x) { for (int i = 0; i < 2; i++) { if (!v[e[x][i]]) { v.set(e[x][i]); if (!~res[e[x][i]] || dfs(res[e[x][i]])) { res[e[x][i]] = x; return true; } } } return false; } inline void swap(int &a, int &b) {a ^= b ^= a ^= b;} int main() { scanf("%d", &n); for (int i = 0; i < n; i++) { int a; scanf("%d", &a); e[i][0] = (i + a) % n; e[i][1] = (i + n - a) % n; if (e[i][0] > e[i][1]) swap(e[i][0], e[i][1]); } memset(res, -1, sizeof res); int tmp = n; for (int i = n - 1; ~i; i--) { v.reset(); if (dfs(i)) tmp--; } if (tmp) { puts("No Answer"); return 0; } for (int i = 0; i < n; i++) ans[res[i]] = i; for (int i = 0; i < n; i++) printf("%d ", ans[i]); puts(""); return 0; }