您的位置:首页 > 理论基础 > 计算机网络

网络流24题——圆桌问题

2016-09-07 20:28 316 查看
假设有来自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 1e8
using 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: