欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - PowerOJ1740 - 有SPJ - 推荐

题目传送门 - CodeVS1905 - 无SPJ - 0% 通过率(可以用来看题目)


题意概括

  有n支队伍,m个组。第i支队伍有a[i]个人,第i个组最多可以有b[i]个人。

  现在要求任何两个同队队员不可位于同一组,求是否有方案满足。

  输出第一行,表示是否有,如果有,是1,没有的话,输出0;

  如果有,接下来n行,第i行a[i]个数,表示第i支队伍的每个人被安排的组号。

  有SPJ,只要输出任意一种方案即可。


题解

  其实就是一个网络流的水题。

  前置技能 - 网络流(传送门)

  对于n支队伍,每只队伍一个点;对于m个组(餐桌),每个组一个点。

  另外地,建立一个源点和一个汇点。

  连接源点和队伍点,对于队伍i,该边的容量为a[i];

  连接每一个组的点和汇点,对于组i,该边的容量为b[i];

  对于每一个队伍,向每个组连一条边,容量为1。

  那么图就构建完了。

  至于证明,不解释了。

  然后跑一跑最大流,就算出了最大匹配数。

  其实,我们可以发现,这是一个二分图多重匹配问题。

  如果无法全部匹配,则输出0,

  否则输出1,再考虑。

  然后对于连接二分图左右两端的边,如果容量为1,那么这条边就是被选择的,那么该边所连接的两个节点,“队伍点”对应“组点”,然后这样就可以把所有的匹配全部还原。

  具体操作见代码。


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
using namespace std;
const int N=,M=N*N,Inf=<<;
struct Edge{int x,y,cap,flow,nxt,flag;};
struct Graph{
int cnt,s,t,n,fst[N],dist[N],cur[N],num[N],p[N],head,tail,q[N];
Edge e[M];
void set(int S,int T,int nn){
s=S,t=T,n=nn,cnt=,memset(fst,,sizeof fst);
}
void add(int a,int b,int c,int d){
e[++cnt].x=a,e[cnt].y=b,e[cnt].cap=c,e[cnt].flow=,e[cnt].flag=d,e[cnt].nxt=fst[a],fst[a]=cnt;
e[++cnt].x=b,e[cnt].y=a,e[cnt].cap=,e[cnt].flow=,e[cnt].flag=,e[cnt].nxt=fst[b],fst[b]=cnt;
}
void re_bfs(){
memset(dist,-,sizeof dist);
memset(q,,sizeof q);
head=tail=dist[t]=;
q[++tail]=t;
while (head<tail)
for (int x=q[++head],i=fst[x];i;i=e[i].nxt)
if (e[i].cap==&&dist[e[i].y]==-)
dist[q[++tail]=e[i].y]=dist[x]+;
for (int i=;i<=n;i++)
if (dist[i]==-)
dist[i]=n;
}
int Augment(int &point){
int ex_Flow=Inf;
for (int i=t;i!=s;i=e[p[i]].x)
if (ex_Flow>=e[p[i]].cap-e[p[i]].flow)
ex_Flow=e[p[i]].cap-e[p[i]].flow,point=e[p[i]].x;
for (int i=t;i!=s;i=e[p[i]].x)
e[p[i]].flow+=ex_Flow,e[p[i]^].flow-=ex_Flow;
return ex_Flow;
}
int SAP(){
int x=s,y,MaxFlow=;
memset(num,,sizeof num);
for (int i=;i<=n;i++)
num[dist[i]]++,cur[i]=fst[i];
while (dist[s]<=n){
if (x==t){
MaxFlow+=Augment(x);
continue;
}
bool found=;
for (int i=cur[x];i!=&&!found;i=e[i].nxt)
if (dist[e[i].y]+==dist[x]&&e[i].cap>e[i].flow)
cur[x]=p[e[i].y]=i,x=e[i].y,found=;
if (found)
continue;
int d=n+;
for (int i=fst[x];i;i=e[i].nxt)
if (e[i].cap>e[i].flow)
d=min(d,dist[e[i].y]+);
if (!(--num[dist[x]]))
return MaxFlow;
num[dist[x]=d]++,cur[x]=fst[x];
if (x!=s)
x=e[p[x]].x;
}
return MaxFlow;
}
}g;
int n,m,a[N],b[N],sum=,mat[N][N];
int main(){
scanf("%d%d",&n,&m);
g.set(n+m+,n+m+,n+m+);
for (int i=;i<=n;i++)
scanf("%d",&a[i]),sum+=a[i],g.add(g.s,i,a[i],);
for (int i=;i<=m;i++)
scanf("%d",&b[i]),g.add(i+n,g.t,b[i],);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
g.add(i,j+n,,);
g.re_bfs();
int Flow=g.SAP();
puts(Flow<sum?"":"");
if (Flow<sum)
return ;
memset(mat,,sizeof mat);
for (int i=;i<=g.cnt;i++)
if (g.e[i].flag==&&g.e[i].cap==&&g.e[i].flow==){
int x=g.e[i].x,y=g.e[i].y-n;
mat[x][++mat[x][]]=y;
}
for (int i=;i<=n;i++)
sort(mat[i]+,mat[i]+mat[i][]+);
for (int i=;i<=n;puts(""),i++)
for (int j=;j<=mat[i][];j++)
printf("%d ",mat[i][j]);
return ;
}

网络流24题 第五题 - PowerOJ1740 CodeVS1905 圆桌问题 二分图多重匹配 网络最大流的更多相关文章

  1. 【网络流24题】No.7 试题库问题 (最大流,二分图多重匹配)

    [题意] 假设一个试题库中有 n 道试题. 每道试题都标明了所属类别. 同一道题可能有多个类别属性.现要从题库中抽取 m 道题组成试卷.并要求试卷包含指定类型的试题. 试设计一个满足要求的组卷算法. ...

  2. hihoCoder 1393 网络流三·二分图多重匹配(Dinic求二分图最大多重匹配)

    #1393 : 网络流三·二分图多重匹配 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 学校的秋季运动会即将开始,为了决定参赛人员,各个班又开始忙碌起来. 小Hi和小H ...

  3. hiho 第117周 二分图多重匹配,网络流解决

    描述 学校的秋季运动会即将开始,为了决定参赛人员,各个班又开始忙碌起来. 小Hi和小Ho作为班上的班干部,统计分配比赛选手的重任也自然交到了他们手上. 已知小Hi和小Ho所在的班级一共有N名学生(包含 ...

  4. HDU 5352——MZL's City——————【二分图多重匹配、拆点||网络流||费用流】

    MZL's City Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  5. 网络流24(san)题题解汇总

    开坑(烂尾预定 1.餐巾计划问题 题解 2.最小路径覆盖问题 题解 3.试题库问题 题解 4.[CTSC1999]家园 题解 5.骑士共存问题 题解 6.最长不下降子序列问题 题解 7.深海机器人问题 ...

  6. 【网络流24题】 No.5 圆桌问题 (多重匹配)

    [题意] 假设有来自 n 个不同单位的代表参加一次国 际会议.每个单位的代表数分别为r i ni , = 1,2, .会议餐厅共有 m 张餐桌,每张餐桌可容纳 ci (i = 1,2, , m) 个 ...

  7. 查找最小的k个元素 【微软面试100题 第五题】

    题目要求: 输入n个整数,输出其中最小的k个. 例如:输入1,2,3,4,5,6,7,8这8个数字,则最小的4个数字为1,2,3,4. 参考资料:剑指offer第30题. 题目分析: 解法一: 用快排 ...

  8. [HIHO1393]网络流三·二分图多重匹配

    题目链接:http://hihocoder.com/problemset/problem/1393 把项目到汇点的边权值都加起来,跑完最大流后看是否最大流=权值和.如果等于权值和说明所有项目都有足够的 ...

  9. POJ3189_Steady Cow Assignment(二分图多重匹配/网络流+二分构图)

    解题报告 http://blog.csdn.net/juncoder/article/details/38340447 题目传送门 题意: B个猪圈,N头猪.每头猪对每一个猪圈有一个惬意值.要求安排这 ...

随机推荐

  1. luogu 1196 银河英雄传说 带权并查集

    带权并查集,其实有点像许多队列问情况的小学奥数 #include<bits/stdc++.h> #define rep(i,x,y) for(register int i=x;i<= ...

  2. MySQL自动设置create_time和update_time

    参考表结构 CREATE TABLE `t_baby` ( `baby_id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, ...

  3. extern的作用

    #include <stdio.h>extern int a;static int a;extern int b;int b;static int c;extern int c;

  4. P3806 【模板】点分治1(CDQ分治)

    题目链接:https://www.luogu.org/problemnew/show/P3806 题目大意:中文题目 具体思路:直接dfs好像会超时,然后我们就开始想优化的方法,然后就是一个CDQ入门 ...

  5. iptables学习笔记_____摘自朱双印个人日志 ____http://www.zsythink.net/

    iptables为我们预先定义了四张表 raw.mangle.nat.filter filter表负责过滤:允许那些ip访问.拒绝那些ip访问.允许那些端口...是最常用的表 #查看表里面所有的规则i ...

  6. SpringBoot与任务

    (1).异步任务 package cn.coreqi; import org.springframework.boot.SpringApplication; import org.springfram ...

  7. Python Tools for Machine Learning

    Python Tools for Machine Learning Python is one of the best programming languages out there, with an ...

  8. SHA1算法原理

    一.SHA1与MD5差异 SHA1对任意长度明文的预处理和MD5的过程是一样的,即预处理完后的明文长度是512位的整数倍,但是有一点不同,那就是SHA1的原始报文长度不能超过2的64次方,然后SHA1 ...

  9. Linux的capability深入分析(1)【转】

    转自:https://blog.csdn.net/wangpengqi/article/details/9821227 一)概述: )从2.1版开始,Linux内核有了能力(capability)的概 ...

  10. Mashup

    简介 mashup是糅合,是当今网络上新出现的一种网络现象,将两种以上使用公共或者私有数据库的web应用,加在一起,形成一个整合应用.一般使用源应用的API接口,或者是一些rss输出(含atom)作为 ...