【洛谷P3254】【24题】圆桌问题【网络流】

题目大意:

题目链接:https://www.luogu.org/problemnew/show/P3254
nn个餐桌mm个公司,每个公司有a[i]a[i]个人,而每个餐桌能容纳b[i]b[i]人。同一个公司的人不能坐在一个餐桌上。求能否满足以上要求。


思路:

卡时卡过的,也不知道为什么会被卡。
这里写图片描述
这里写图片描述
这里写图片描述
这道题很明显最大流。公司放左边,桌子放右边,原点连公司,流量为公司人数,汇点连桌子,流量为可以容纳的人数。所有公司依次和所有桌子相连,流量为1。
然后跑一边最大流即可。


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 1e9
using namespace std;

int n,m,k,head[800001],dep[800001],s,t,x,sum,num,ans,p[501][801],peo[801];

struct edge
{
    int next,c,to;
}e[2000001];

void add(int from,int to,int c)  //建模
{
    k++;
    e[k].to=to;
    e[k].c=c;
    e[k].next=head[from];
    head[from]=k;
}

bool bfs()  //分层
{
    memset(dep,0x3f3f3f3f,sizeof(dep));
    queue<int> q;
    q.push(s);
    dep[s]=0;
    while (q.size())
    {
        int u=q.front();
        q.pop();
        for (int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if (dep[v]>dep[u]+1&&e[i].c)
            {
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }
    return (dep[t]<0x3f3f3f3f);
}

int dfs(int u,int low)  //找增广路
{
    int lows=0;
    if (u==t) return low;
    for (int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if (dep[v]==dep[u]+1&&e[i].c)
        {
            lows=dfs(v,min(low,e[i].c));
            if (!lows) continue;
            e[i].c-=lows;
            e[i^1].c+=lows;
            return lows;
        }
    }
    return 0;
}

void print()  //输出方案
{
    for (int i=n+1;i<=n+m;i++)
     for (int j=head[i];j;j=e[j].next)
     {
        int v=e[j].to;
        if (v<t&&e[j].c)
         p[v][++peo[v]]=i-n;  //每个公司的人坐的餐桌
     }
    for (int i=1;i<=n;i++)
    {
    	for (int j=1;j<=peo[i];j++)
      	 printf("%d ",p[i][j]);
      	printf("\n");
    } 
}

int main()
{
    scanf("%d%d",&n,&m);
    k=1;
    s=n+m+10;
    t=n+m+11;
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        num+=x;
        add(s,i,x);
        add(i,s,0);
        for (int j=n+1;j<=n+m;j++)
        {
            add(i,j,1);
            add(j,i,0);
        }
    }
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&x);
        add(n+i,t,x);
        add(t,n+i,0);
    }
    while (bfs())
    {	
        while (sum=dfs(s,INF))
         ans+=sum;
    }
    if (ans<num) return printf("0\n")&0;
    printf("1\n");
    print();
    return 0;
}
原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998638.html