题目:

假设有来自n 个不同单位的代表参加一次国际会议。每个单位的代表数分别为ri, i=1,2,...,n。会议餐厅共有m张餐桌,每张餐桌可容纳ci (i=1,2,...,m)个代表就餐。为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。试设计一个算法,
给出满足要求的代表就餐方案。编程任务:对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案。
• m<=150,n<=270

题解:

关键在于如何建图
具体建图如下:

  1. 将源点S与每个单位链接一条流量为此单位代表数的边
  2. 将每张桌子与汇点T连一条流量为此桌子容量的边
  3. 将每个单位与每张桌子连一条流量为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);
    }
}