博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[NOI2009]变换序列
阅读量:6951 次
发布时间:2019-06-27

本文共 4393 字,大约阅读时间需要 14 分钟。

读懂题意后发现这道题最主要是要求出字典序最小的排列,考察了匈牙利算法的实质。

首先对于$D_i$的定义,我们可以解出可能的$T_i$,然后将$i$与$T_i$连边,求最大匹配。

如果最大匹配$<N$则说明$"No\ Answer"$。

但是要求字典序最小

第一中方法在我$AC$后翻看题解而写的。

这个程序是根据匈牙利算法的实质写的。

对于一个待匹配点,如果从其中一条非匹配边能匹配上,则这条匹配边一定会被匹配上

我们将所有$i$连向$T_i$的边从小到大排序,从最后一个点开始匹配,从小的$T_i$到大的$T_i$判断。最后答案一定是字典序最小的。

为什么呢?根据刚刚的总结,也就是能保证第$1$个点一定能选择最好的匹配,因为非匹配边从最好的往最坏的情况枚举,匹配上的一定就是最好的,因为假如前面没有匹配上,原因就在于选择前面的边一定不能匹配。

1 #include 
2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b);10 #define LL long long11 #define inf (1 << 30)12 13 inline int read() {14 int w = 0, f = 1; char c = getchar();15 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();16 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();17 return w * f;18 }19 20 const int maxn = 1e4 + 5;21 22 int N, D[maxn], e[maxn][5], s[maxn], t[maxn];23 24 int lk[maxn], pt[maxn], vis[maxn];25 26 bool find(int u, int tag) {27 rep(i, s[u], t[u]) {28 int v = e[u][i];29 if (vis[v] != tag) {30 vis[v] = tag;31 if (lk[v] == -1 || find(lk[v], tag)) {32 lk[v] = u;33 pt[u] = v;34 return true;35 }36 }37 }38 return false;39 }40 41 int main() {42 N = read();43 44 rep(i, 0, N-1) {45 D[i] = read();46 e[i][1] = D[i]+i, e[i][2] = i-D[i], e[i][3] = N+i-D[i], e[i][4] = D[i]-N+i;47 sort(e[i]+1, e[i]+5);48 s[i] = 1, t[i] = 4;49 while (s[i] <= 4 && e[i][s[i]] < 0) s[i]++;50 while (t[i] > 0 && e[i][t[i]] >= N) t[i]--;51 }52 53 memset(vis, -1, sizeof(vis));54 memset(lk, -1, sizeof(lk));55 repd(i, N-1, 0)56 if (!find(i, i)) {57 printf("No Answer");58 return 0;59 }60 61 rep(i, 0, N-1)62 printf("%d ", pt[i]);63 64 return 0;65 }

第二种方法是我自己想到的,比上面的代码复杂。

首先有一点:由非匹配边和匹配边交替构成的回路(断句)翻转所有边的匹配与否(断句)得到的是另一种匹配。

所以我们先找出一个最大匹配,再通过上面的结论从第一个点调整使得解更优。最后同样也能得到字典序最小的匹配。

1 #include 
2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b);10 #define LL long long11 #define inf (1 << 30)12 13 inline int read() {14 int w = 0, f = 1; char c = getchar();15 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();16 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar();17 return w * f;18 }19 20 const int maxn = 1e4 + 5;21 22 int N, D[maxn], e[maxn][5], s[maxn], t[maxn];23 24 int lk[maxn], pt[maxn], vis[maxn];25 26 bool find(int u, int tag) {27 rep(i, s[u], t[u]) {28 int v = e[u][i];29 if (vis[v] != tag) {30 vis[v] = tag;31 if (lk[v] == -1 || find(lk[v], tag)) {32 lk[v] = u;33 pt[u] = v;34 return true;35 }36 }37 }38 return false;39 }40 41 bool dfs(int u, int rt) {42 rep(i, s[u], t[u]) {43 int v = e[u][i];44 if (lk[v] < rt) continue;45 if (v == pt[u]) {46 if (u == rt) return false;47 continue;48 }49 if (vis[v] != rt) {50 vis[v] = rt;51 if (lk[v] == rt || dfs(lk[v], rt)) {52 lk[v] = u;53 pt[u] = v;54 return true;55 }56 }57 }58 return false;59 }60 61 int main() {62 N = read();63 64 rep(i, 0, N-1) {65 D[i] = read();66 e[i][1] = D[i]+i, e[i][2] = i-D[i], e[i][3] = N+i-D[i], e[i][4] = D[i]-N+i;67 sort(e[i]+1, e[i]+5);68 s[i] = 1, t[i] = 4;69 while (s[i] <= 4 && e[i][s[i]] < 0) s[i]++;70 while (t[i] > 0 && e[i][t[i]] >= N) t[i]--;71 }72 73 memset(vis, -1, sizeof(vis));74 memset(lk, -1, sizeof(lk));75 rep(i, 0, N-1)76 if (!find(i, i)) {77 printf("No Answer");78 return 0;79 }80 81 memset(vis, -1, sizeof(vis));82 rep(i, 0, N-1)83 dfs(i, i);84 85 rep(i, 0, N-1)86 printf("%d ", pt[i]);87 88 return 0;89 }

 

转载于:https://www.cnblogs.com/ac-evil/p/10351036.html

你可能感兴趣的文章
VMware基础架构和运营管理
查看>>
爱不意味这“sorry”
查看>>
四、 vSphere 6.7 U1(四):部署VCSA
查看>>
apper安卓×××
查看>>
大型网站技术架构(一)大型网站架构演化
查看>>
Log4j 1使用教程
查看>>
如何将PDF转换成Word
查看>>
plusgantt的项目管理系统实战开发最全课程
查看>>
vlan理论03-vlan映射
查看>>
Linux终端的总结和shell
查看>>
Java8 十大新特性详解
查看>>
Maven学习总结(五)——聚合与继承
查看>>
Oracle AWR 阙值影响历史执行计划
查看>>
集成显卡连接显示器的线跟独立显卡的不同么,分别叫什么
查看>>
我的友情链接
查看>>
Java是传值还是传引用
查看>>
文件夹权限
查看>>
【翻译】Siesta事件记录器入门
查看>>
将Ext JS 5应用程序导入Web项目以及实现本地化
查看>>
HTML5开发手机项目—个人总结
查看>>