其他分享
首页 > 其他分享> > 洛谷P3254 圆桌问题

洛谷P3254 圆桌问题

作者:互联网

题目大意:

有\(m\)个单位,每个单位有\(r_i\)个人

共有\(n\)个桌子,每张桌子可以容纳\(c_i\)个人

现在要求每个单位每张桌子只能做一个人,求满足要求的方案

\(m\le 150,n\le 270\)

二分图多重匹配,这里采用网络流解法

单位作为二分图的左部,桌子作为二分图右部

由于每个单位每张桌子只能坐一个人,所以每个单位向每个桌子连一条容量为\(1\)的边。

源点向每个单位连容量为\(r_i\)的边,每张桌子向汇点连容量为\(c_i\)的边,跑一下最大流,看看最大流是否等于\(\sum\limits_{i=1}^{m}r_i\)

统计答案直接枚举

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch;
    for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    if(ch=='-') f=0,ch=getchar();
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?x:-x;
}
const int inf=0x7f7f7f7f;
int n,m,st,ed,ret,sum;
int head[10010],cur[10010],d[10010],cnt=1;
struct node
{
    int nxt,to,val;
}a[100010];
inline void add(int x,int y,int z)
{
    a[++cnt].nxt=head[x];
    a[cnt].to=y;
    a[cnt].val=z;
    head[x]=cnt;
}
queue<int> q;
inline bool bfs()
{
    for(int i=1;i<=n+m+2;++i)
    {
        cur[i]=head[i];
        d[i]=0;
    }
    q.push(st);d[st]=1;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=head[now];i;i=a[i].nxt)
        {
            int t=a[i].to;
            if(!d[t]&&a[i].val)
            {
                d[t]=d[now]+1;
                q.push(t);
            }
        }
    }
    return d[ed];
}
inline int dfs(int now,int c)
{
    if(now==ed||!c) return c;
    int ret=c,f;
    for(int i=cur[now];i;i=a[i].nxt)
    {
        cur[now]=i;
        int t=a[i].to;
        if(d[t]==d[now]+1)
        {
            f=dfs(t,min(a[i].val,ret));
            if(!f) continue;
            a[i].val-=f;
            a[i^1].val+=f;
            ret-=f;
            if(!ret) return c;
        }
    }
    if(c==ret) d[now]=0;
    return c-ret;
}
inline void dinic()
{
    while(bfs()) ret+=dfs(st,inf);
    if(ret!=sum)//最大流是否等于人数
    {
        puts("0");
        return;
    }
    puts("1");
    for(int x=1;x<=m;++x)
    {
        for(int i=head[x];i;i=a[i].nxt)
        {
            int t=a[i].to;
            if(t<=m||t>n+m||a[i].val) continue;
            printf("%d ",t-m);
        }
        putchar('\n');
    }
}
signed main()
{
    m=read(),n=read();
    st=n+m+1,ed=n+m+2;
    for(int x,i=1;i<=m;++i)//每个单位和源点连边,边权为人数
    {
        x=read();
        add(st,i,x);
        add(i,st,0);
        sum+=x;
    } 
    for(int x,i=1;i<=n;++i)//每张桌子和汇点连边,边权为容量
    {
        x=read();
        add(i+m,ed,x);
        add(ed,i+m,0);
        for(int j=1;j<=m;++j)//单位和桌子连边,边权为1限制人数
        {
            add(j,i+m,1);
            add(i+m,j,0);
        }
    }
    dinic();
return 0;
}

标签:ch,洛谷,int,每张,单位,桌子,圆桌,P3254,getchar
来源: https://www.cnblogs.com/knife-rose/p/12095034.html