题意:给 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. 【杂谈】拍了几张照片
  2. document.domain 跨域问题[转]
  3. BZOJ-2780 Sevenk Love Oimaster(广义后缀自动机)
  4. CodeForces - 1228B Filling the Grid(思维,水题)
  5. mysql数据库备份心得
  6. JavaFX的科幻用户界面第1部分
  7. linux连接svn上代码,代码管理平台介绍、安装svn、客户端上使用svn(linux)、客户端上使用svn(windows)...
  8. .Net 自定义应用程序配置 configSections
  9. [Java][内存模型]
  10. android ctrl 左键鼠标左键直接打开xml文件夹,android – 在listview项目上单击打开xml文件...
  11. java jsch shell_仅在JSch shell通道中获取特定命令的输出
  12. Android之adb安装apk
  13. 一.微信公众号迁移流程 openid转换
  14. 氨基酸序列碎裂by离子-生物信息学笔记
  15. 富文本编辑器ueditor——找不到ueditor.all.js以及ueditor.all.min.js文件
  16. pandas concat “InvalidIndexError: Reindexing only valid with uniquely valued Index objects“
  17. 前端程序员兼职副业平台推荐
  18. 初步使用计算机的教学反思,静夜思教学反思(精选10篇)
  19. 网站开发进阶(二十六)js刷新页面方法大全
  20. element-ui 滚动条样式修改

热门文章

  1. 微信又添新功能!这个微信群可以学英语,而且全程免费
  2. 机器学习的最佳学习路线,就在这里!
  3. mySQL微信小程序的div_做一个微信小程序的完整流程
  4. 二维数组各行分别求和_【PyTorch入门】之十分钟看懂二维卷积层的运算、实现及应用...
  5. lua传值到php,使用lua实现php的var_dump()函数功能
  6. 期货市场计算机分析指南在线,期货市场计算机分析指南
  7. java多线程 sycophantic_Java多线程volatile和synchronized总结
  8. bios是固定在微型计算机上的一块RoM,计算机硬件笔试试题
  9. java collator_Java Collator compare(String, String)用法及代码示例
  10. 在安卓上安装java_如何在Android上安装JavaCV并使用FrameGrabber