[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nCz1IW6I-1587115186867)(http://www.lydsy.com/JudgeOnline/images/1562_1.jpg)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-GiPTbzO5-1587115186870)(http://www.lydsy.com/JudgeOnline/images/1562_2.jpg)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-i3tLhCEJ-1587115186874)(http://www.lydsy.com/JudgeOnline/images/1562_3.jpg)]
Sample Input
5
1 1 2 2 1
Sample Output
1 2 4 0 3
HINT
30%的數據中N≤50;
60%的數據中N≤500;
100%的數據中N≤10000。
如果原序列中的x位置的數可以放在新序列的y位置上 就連一條x到y的邊 跑一遍二分圖
如果hungary()==n 則有解
由於要字典序最小 要反着跑匈牙利算法 因爲匈牙利算法會讓之後拓展到的結點擠掉之前結點的匹配
還要讓結點從小到大排 讓字典序最小
最後在dfs的過程中 同時記錄link和ans
#include<vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define v1 (i+d)%n
#define v2 (i-d+n)%n
inline int read() {
int s = 0, f = 1; char c = getchar(); while (c<'0' || c>'9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0'&&c <= '9') { s = s * 10 + c - '0'; c = getchar(); }
return s*f;
}
int n;
const int maxn = 10007;
vector<int> g[maxn << 1];
bool vis[maxn << 1];
int link[maxn << 1],ans[maxn<<1];
bool dfs(int u) {
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if (!vis[v]) {
vis[v] = true;
if (link[v]==-1 || dfs(link[v])) {
link[v] = u;
ans[u] = v;
return true;
}
}
}
return false;
}
int hungary() {
int res = 0;
memset(link, -1, sizeof(link));
for (int i = n - 1; i >= 0; i--) {
memset(vis, false, sizeof(vis));
if (!dfs(i)) {
//puts("No Answer");
return -1;
}
res++;
}
//printf("%d\n", res);
return res;
}
int main() {
n = read();
int d;
for (int i = 0; i < n; i++) {
d = read();
g[i].push_back(v1);
g[i].push_back(v2);
}
for (int i = 0; i < n; i++) sort(g[i].begin(), g[i].end());
//保證在dfs過程中先考慮較小的那個點
if (hungary() == n) {
for (int i = 0; i < n - 1; i++)
printf("%d ", ans[i]);
printf("%d", ans[n - 1]);
}
else {
puts("No Answer");
}
//getchar();
return 0;
}