题意:给 n×mn\times mn×m 的表格填入 [1,max⁡(n,m)][1,\max(n,m)][1,max(n,m)] 的数,每行每列不能重复,且字典序最小。

n,m≤50n,m\leq 50n,m≤50

数据范围很小,所以是多项式就能过。

考虑每个位置从小到大依次填值,判断之后是否有合法解。

当 n≤mn\leq mn≤m 时所有数和没用过的列做二分图匹配就可以了。但 n>mn>mn>m 时就变成了三分图匹配,没法做。

然后是个结论:当 n>mn>mn>m 时,填了 xxx 行,问题有解当且仅当每个数还需要填的个数不超过剩余行数。显然每个数必须恰好填 nnn 个,所以这个“需要填的个数”是确定的。

必要性显然,充分性后述。

考虑每一行,有一些数是这一列必须匹配的,其余数可以匹配也可以不匹配。可以用匈牙利限制顺序或上下界网络流解决。

现在证明一定存在满匹配。考虑 Hall 定理,左边是所有数,右边是所有列,有连边当且仅当这个数没在这列出现过。我们任意选择 iii 列,有满匹配的充要条件是这 iii 列对应的点的邻边的交集大小 ≥k\geq k≥k。假设交集小于 kkk,那么一定有一种数在后面出现了 >ixi=x>\dfrac{ix}{i}=x>iix​=x 次,其中 xxx 为剩余行数,与已知矛盾,故得证。

然后直接跑就行了。复杂度 O(poly(n,m))\Omicron(poly(n,m))O(poly(n,m))

代码的题不太一样,仅供参考

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <queue>
#define MAXN 65
#define MAXM 2077
using namespace std;
const int INF=0x7fffffff;
struct edge{int u,v,c;}e[MAXM];
int head[MAXN],cur[MAXN],nxt[MAXM],cnt=1;
inline void insert(int u,int v,int c){e[++cnt]=(edge){u,v,c};nxt[cnt]=head[u];head[u]=cnt;}
inline void addnode(int u,int v,int c){insert(u,v,c),insert(v,u,0);}
int dis[MAXN],S,T,SS,TT;
bool bfs(int S,int T)
{queue<int> q;q.push(T);memset(dis,-1,sizeof(dis));dis[T]=0;while (!q.empty()){int u=q.front();q.pop();for (int i=head[u];i;i=nxt[i])if (e[i^1].c&&dis[e[i].v]==-1){dis[e[i].v]=dis[u]+1;q.push(e[i].v);if (e[i].v==S) return true;}}return false;
}
int dfs(int u,int f,int T)
{if (u==T||!f) return f;int used=0;for (int& i=cur[u];i;i=nxt[i])if (e[i].c&&dis[u]==dis[e[i].v]+1){int w=dfs(e[i].v,min(e[i].c,f),T);e[i^1].c+=w,e[i].c-=w;used+=w,f-=w;if (!f) break;}if (!used) dis[u]=-1;return used;
}
inline int dinic(int S,int T){int ans=0;while (bfs(S,T)) memcpy(cur,head,sizeof(cur)),ans+=dfs(S,INF,T);return ans;}
inline void clear(){memset(head,0,sizeof(head));for (int i=2;i<=cnt;i++) nxt[i]=0;cnt=1;}
int a[MAXN][MAXN],vis[MAXN][MAXN],now[MAXN],res[MAXN];
int n,m,lim,vip[MAXN],tot;
bool check(int y)
{clear();int sum=0;for (int i=1;i<=lim;i++) if (!now[i]) {if (vip[i]) addnode(SS,i,1),++sum;else addnode(S,i,1);}addnode(T,S,INF),addnode(S,TT,sum);for (int i=y+1;i<=m;i++) addnode(i+lim,T,1);for (int i=1;i<=lim;i++)if (!now[i])for (int j=y+1;j<=m;j++)if (!vis[j][i])addnode(i,j+lim,1);if (dinic(SS,TT)<sum) return false;return dinic(S,T)==m-y;
}
int main()
{for (n=1;n<=30;n++)for (m=1;m<=30;m++){lim=max(n,m);S=2*lim+1,T=S+1,SS=T+1,TT=SS+1;for (int i=1;i<=lim;i++) res[i]=n+m-lim;for (int i=1;i<=n;i++){for (int j=1;j<=lim;j++) vip[j]=(res[j]==n-i+1); for (int j=1;j<=m;j++)while (++a[i][j]){if (now[a[i][j]]||vis[j][a[i][j]]) continue;now[a[i][j]]=1,vis[j][a[i][j]]=1;if (check(j)) break;now[a[i][j]]=0,vis[j][a[i][j]]=0;}for (int j=1;j<=m;j++) --res[a[i][j]];memset(now,0,sizeof(now));   }for (int i=1;i<=n;i++,puts(""))for (int j=1;j<=m;j++)printf("%d ",a[i][j]);puts("");memset(a,0,sizeof(a)),memset(vis,0,sizeof(vis));       }return 0;
}

【TC10738】TheContest【Hall 定理】【贪心】【二分图匹配】相关推荐

  1. Hall定理(bzoj 1135: [POI2009]Lyz)

    Hall定理(二分图重要定理): 对于二分图U, V(|U|<|V|),设M(Ux)为V中可以与Ux中的点相连的点集,如果该二分图存在完美匹配 那么对于任意点集x∈U都有|M(x)|>=| ...

  2. Hall定理及其充要性证明

    Hall定理: 若二分图GGG中两部分的点的集合分别为X,YX,YX,Y下设∣X∣≤∣Y∣|X| \leq |Y|∣X∣≤∣Y∣ 则二分图存在完备匹配当且仅当XXX中的任意kkk个点至少与YYY中的k ...

  3. 二分图的Hall定理

    Hall定理的作用: 用于判断二分图是否存在完美匹配 完美匹配: 二分图的最大匹配数为min(|X|,|Y|),即X和Y中有一个集合所有点都被匹配 Hall定理: 设|X|<=|Y|,二分图XY ...

  4. 二分图匹配的 König定理

    二分图最小顶点覆盖: 选择数量最少的点集,满足图中每条边至少和点集中的一个点关联 König定理: 二分图最小顶点覆盖=二分图最大匹配 简单证明: 设最大匹配为M 1.M足够:让选出的点集覆盖这M条匹 ...

  5. TCO 2015 1A Hard.Revmatching(Hall定理)

    \(Description\) 给定一个\(n\)个点的二分图,每条边有边权.求一个边权最小的边集,使得删除该边集后不存在完备匹配. \(n\leq20\). \(Solution\) 设点集为\(S ...

  6. 二分图匹配及匈牙利算法的全面讲解及python实现

    1.背景 在生活中常常遇到两组元素多对多匹配而又数目有限的情况,我们需要对其进行最大匹配数的分配,使效率最大化.例如,有一组压缩气缸和一组压缩活塞,每一个型号的压缩气缸有一个固定的内径大小,每一个型号 ...

  7. 算法讲解:二分图匹配

    二分图匹配,自然要先从定义入手,那么二分图是什么呢? 二分图: 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每 ...

  8. 二部图Hall定理学习笔记

    离散数学PPT: Hall定理 定理(Hall定理) 设二部图G=<V1,V2,E>中,|V1|≤|V2|. G中存在从V1到V2的完备匹配当且仅当V1中任意k 个顶点至少与V2中的k个顶 ...

  9. 算法讲解:二分图匹配【图论】

    二分图匹配,自然要先从定义入手,那么二分图是什么呢? 二分图: 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每 ...

最新文章

  1. 2018 年度 GtiHub 开源项目 TOP 25:数据科学 机器学习
  2. 【JavaSE03】Java中分支语句-思维导图
  3. MySQL的高级运用_MYSQL之SQL高级运用(帮助你高效率编程)
  4. cocos2d-x android 入门
  5. 定制安装centos6.4系统 上汽集团线上环境
  6. Python获取文件路径:os.listdir()和os.walk()
  7. ExactScan pro for mac(扫描仪整合工具)
  8. 架构师补给站之EA(企业架构)
  9. 面试题:ES和Solr的区别是什么?
  10. Abaqus之地应力平衡分析步 Geostatic step
  11. 移植MPlay到mini2440开发板
  12. php编码小坑之调用新浪天气api和阿凡达天气api
  13. 有符号和无符号相加(vivo)
  14. python 技巧总结_python技巧汇总
  15. UVa——1600(巡逻机器人)
  16. CLR,CTS,CLS
  17. 正则表达式到底是什么?
  18. html5--2.9新的布局元素(5)-hgroup/address
  19. pmos低电平驱动_MOS管的低端驱动和高端驱动
  20. linux 删除网卡配置文件,linux-如何通过命令行/ shell脚本从etc / wpa_supplicant / wpa_supplicant.conf中删除网络配置文件...

热门文章

  1. 全地球的水也没办法将这个“特殊”的瓶子装满!
  2. 学过物理的人才能看懂的笑话,你能看明白几个?
  3. 每日一笑 | 一些关于学编程的领悟
  4. 离职总结:大公司与小公司的个人体验
  5. 一些奇葩的元素节点object,video
  6. java 继承与多态 习题_JAVA基础 第4章继承与多态_练习题_200910
  7. 密封槽设计标准_哈尔滨轴承 | 超全面机械密封选型
  8. mysql 常用权限_MySQL的权限有哪些
  9. $.ajax datatype默认是什么类型,理解jquery ajax中的datatype属性选项值
  10. java consumer 使用_java.util.function.Consumer的用法