题目:
假设有来自n 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri, i=1,2,...,n。会议餐厅共有m张餐桌,每张餐桌可容纳ci (i=1,2,...,m)个代表就餐。为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,
给出满足要求的代表就餐方案。编程任务:对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
• m<=150,n<=270
题解:
关键在于如何建图
具体建图如下:
- 将源点S与每个单位链接一条流量为此单位代表数的边
- 将每张桌子与汇点T连一条流量为此桌子容量的边
- 将每个单位与每张桌子连一条流量为1的边
然后跑遍网络流,结果sum如果等于所有人数,则说明匹配成功,可以安排入座
至于具体方案,在跑完网络流后,单位与桌子的边权如果为0说明已经匹配,如果为1则说明为匹配,我们输出边权为0的即可
但是我现在遇到一点问题,对于样例4 5 4 5 3 5 3 5 2 6 4
我匹配出来的最大流是16,而不是17,少一个
第二个单位代表少匹配一个圆桌
不知道是网络流模板错了,还是哪里错了,搞不明白。。。emmm
代码;
#include<bits/stdc++.h> #define mem(x) memset(x,0,sizeof(x)) #define INF 0x3f3f3f typedef long long ll; using namespace std; inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48); return s*w; } const int maxn=1009; int a[maxn],b[maxn]; struct node{ int u,v,next,w; }edge[maxn]; int cnt,head[maxn]; void add(int u,int v,int w) { edge[++cnt].u=u; edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt; edge[++cnt].u=v; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt; } int vis[maxn],level[maxn]; bool bfs(int s,int t) { queue<int>q; q.push(s); level[s]=1; while(!q.empty()) { int u=q.front(); q.pop(); if(u==t)return 1; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; int w=edge[i].w; if(level[v]==0&&w>0) { q.push(v); level[v]=level[u]+1; } } } return 0; } int dfs(int u,int flow,int t) { if(u==t)return flow; int sum=0; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; int w=edge[i].w; if(w&&level[v]==level[u]+1) { int tmp=dfs(v,min(flow-sum,w),t); edge[i].w-=tmp; edge[i^1].w+=tmp; sum+=tmp; if(sum==flow)return sum; } } return sum; } int s=0,t=1000; int dinic() { int sum=0; while(bfs(s,t)) { sum+=dfs(s,INF,t); } return sum; } int m,n; void put(int u) { for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v;; int w=edge[i].w; if(v!=s&&w==0)cout<<v-m<<" "; } printf("\n"); } int main() { cin>>m>>n; int tot=0; for(int i=1;i<=m;i++)cin>>a[i]; for(int i=1;i<=n;i++)cin>>b[i]; for(int i=1;i<=m;i++) { tot+=a[i]; add(s,i,a[i]); } for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { add(i,j+m,1); } } for(int i=1;i<=n;i++) { add(i+m,t,b[i]); } int w=dinic(); if(w==tot)cout<<1<<endl; else { cout<<0<<endl; return 0; } for(int i=1;i<=m;i++) { put(i); } }