网络流24题——圆桌问题
来源:互联网 发布:有人招聘网络写手吗? 编辑:程序博客网 时间:2024/04/30 03:20
假设有来自n 个不同单位的代表参加一次国际会议。每个单位的代表数分别为
ri,i=1,2,…,n 。会议餐厅共有m张餐桌,每张餐桌可容纳ci(i=1,2, ,m) 个代表就餐。
为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,
给出满足要求的代表就餐方案。
编程任务:
对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
样例输入
由文件input.txt提供输入数据。文件第1行有2 个正整数m和n,m表示单位数,n表
示餐桌数,1<=m<=150, 1<=n<=270。文件第2 行有m个正整数,分别表示每个单位的代表
数。文件第3 行有n个正整数,分别表示每个餐桌的容量。
输出格式
程序运行结束时,将代表就餐方案输出到文件output.txt 中。如果问题有解,在文件第
1 行输出1,否则输出0。接下来的m行给出每个单位代表的就餐桌号。如果有多个满足要
求的方案,只要输出1 个方案。
样例输入
4 5
4 5 3 5
3 5 2 6 4
样例输出
1
1 2 4 5
1 2 3 4 5
2 4 5
1 2 3 4 5
唔,感觉没什么难的啊,就是很简单的搞定了。
就是很简单的二分图多重匹配的问题。
(我才知道,原来这个是多重匹配而不是匹配的变式)
唔,注意这个:
- 如果最大流量等于所有单位人数之和,则存在解,否则无解
#include<cstdio> #include<vector> #include<queue> #include<cstring> #define INF 1e8using namespace std;const int maxn=500; struct Edge{int from,to,cap,flow;}; vector<Edge>edges; vector<int>G[maxn]; int s,t,d[maxn],cur[maxn]; int a[maxn],b[maxn]; bool vis[maxn];void AddEdge(int from,int to,int cap){ edges.push_back((Edge){from,to,cap,0}); edges.push_back((Edge){to,from,0,0}); int sz=edges.size(); G[from].push_back(sz-2); G[to].push_back(sz-1); } void Build(int n,int m){ s=0,t=n+m+1; for(int i=1;i<=n;i++){ AddEdge(s,i,a[i]); for(int j=1;j<=m;j++) AddEdge(i,j+n,1); } for(int i=1;i<=m;i++) AddEdge(i+n,t,b[i]); } bool BFS(){ memset(vis,false,sizeof(vis)); queue<int>Q;Q.push(s); d[s]=0;vis[s]=true; while(!Q.empty()){ int u=Q.front();Q.pop(); for(int i=0;i<G[u].size();i++){ Edge& e=edges[G[u][i]]; if(!vis[e.to] && e.cap>e.flow){ vis[e.to]=true; d[e.to]=d[u]+1; Q.push(e.to); } } } return vis[t]; } int DFS(int u,int a){ if(u==t || a==0) return a; int f,flow=0; for(int& i=cur[u];i<G[u].size();i++){ Edge& e=edges[G[u][i]]; if(d[e.to]==d[u]+1 && (f=DFS(e.to,min(a,e.cap-e.flow)))>0){ e.flow+=f; edges[G[u][i]^1].flow-=f; flow+=f; a-=f; if(a==0)break; } } return flow; } int dinic(){ int flow=0; while(BFS()){ memset(cur,0,sizeof(cur)); flow+=DFS(s,INF); } return flow; } void Print(int n,int m){ for(int u=1;u<=n;u++){ for(int i=0;i<G[u].size();i++){ Edge& e=edges[G[u][i]]; if(e.flow==1 && e.to!=t) printf("%d ",e.to-n); } printf("\n"); } } int main(){ int n,m; scanf("%d%d",&n,&m); int sum=0; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum+=a[i]; } for(int i=1;i<=m;i++) scanf("%d",&b[i]); Build(n,m); int flow=dinic(); if(flow>=sum){ printf("1\n"); Print(n,m); } else printf("0\n"); return 0; }
0 0
- 网络流24题——圆桌问题
- 网络流24题之T5——圆桌问题
- [网络流24题 #5]圆桌问题
- 【网络流24题】圆桌问题
- 网络流24题之圆桌问题
- 网络流24题5 圆桌问题
- 网络流24题5 圆桌问题
- 【网络流24题】圆桌问题
- 网络流24题5. 圆桌问题
- 线性规划与网络流24——圆桌问题
- 线性规划与网络流24题 05圆桌问题
- 网络流与线性规划24题05圆桌问题
- kyeremal-网络流24题T5-圆桌问题
- 圆桌问题【二分图多重匹配】网络流24题
- 网络流24题之五 圆桌问题 最大匹配
- 圆桌问题[网络流24题之5]
- 【线性规划与网络流24题 5】圆桌问题
- 线性规划与网络流24题之 圆桌问题
- 八皇后问题(典型的递归回溯)
- Activity和WMS关系梳理
- C-1-11-1 分离各位数
- 重拾算法(三):求最大公约数的常用方法总结
- 第二周项目二 程序的多文件组织
- 网络流24题——圆桌问题
- Oracle位图例子
- 五大主流深度学习框架比较分析:MXNET是最好选择
- HDU:Let the Balloon Rise
- 51nod1006 最长公共子序列Lcs--打表+输出
- 金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)->(一千零一拾一元整)输出。
- Red Black Tree(红黑树)
- mvc 自带验证使用
- 1007. Maximum Subsequence Sum (25)