LibreOJ 6004 圆桌聚餐 (最大流)

题解:天啊,这道最大流真是水的一批……只需要每张桌子向每个单位建一条容量为1的边,源点向桌子建边,容量为桌子能坐的人数;单位向汇点建边,容量为单位人数即可,然后根据单位与桌子的连边值是否为一来了解每个单位配对的桌子即可

代码如下:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;

int head[100010],next[100010],w[100010],v[100010],deep[100010],cur[100010];
int n,m,s,t,cnt;

int init()
{
    cnt=-1;
    memset(head,-1,sizeof(head));
    memset(next,-1,sizeof(next));
}

void add(int from,int to,int cost)
{
    cnt++;
    next[cnt]=head[from];
    w[cnt]=cost;
    v[cnt]=to;
    head[from]=cnt;
} 

void add_edge(int from,int to,int cost)
{
    add(from,to,cost);
    add(to,from,0);
}

int bfs(int s,int t)
{
    queue<int> q;
    memset(deep,0,sizeof(deep));
    deep[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=next[i])
        {
            if(w[i]>0&&!(deep[v[i]]))
            {
                deep[v[i]]=deep[u]+1;
                q.push(v[i]);
            }
        }
    }
    if(!deep[t])
    {
        return 0;
    }
    return 1;
}

int dfs(int u,int t,int dist)
{
    if(u==t)
    {
        return dist;
    }
    for(int &i=cur[u];i!=-1;i=next[i])
    {
        if(deep[v[i]]==deep[u]+1&&w[i]!=0)
        {
            int di=dfs(v[i],t,min(dist,w[i]));
            if(di>0)
            {
                w[i]-=di;
                w[i^1]+=di;
                return di;
            }
        }
    }
    return 0;
}

int dinic(int s,int t)
{
    int res=0;
    while(bfs(s,t))
    {
        for(int i=s;i<=t;i++)
        {
            cur[i]=head[i];
        }
        while(int di=dfs(s,t,inf))
        {
            res+=di;
        }
    }
    return res;
}

int main()
{
    int a[1000],b[1000],sum=0;
    vector<int> g[1000];
    scanf("%d%d",&m,&n);
    init();
    s=0;t=n+m+1;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&a[i]);
        add_edge(i+n,t,a[i]);
        sum+=a[i];

    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&b[i]);
        add_edge(s,i,b[i]);
        for(int j=1;j<=m;j++)
        {
            add_edge(i,j+n,1);
        }
    }
    int ans=dinic(s,t);
    if(ans==sum)
    {
        puts("1");
    }
    else
    {
        puts("0");
        return 0;
    }
    for(int i=head[t];i!=-1;i=next[i])
    {
        for(int j=head[v[i]];j!=-1;j=next[j])
        {
            if(w[j]&&v[j]!=t)
            {
                g[v[i]-n].push_back(v[j]);
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<g[i].size();j++)
        {
            printf("%d ",g[i][j]);
        }
        printf("\n");
    }
}

原文地址:https://www.cnblogs.com/stxy-ferryman/p/8584489.html

时间: 2024-08-29 22:12:35

LibreOJ 6004 圆桌聚餐 (最大流)的相关文章

LiberOJ 6004. 「网络流 24 题」圆桌聚餐 网络流版子题

#6004. 「网络流 24 题」圆桌聚餐 内存限制:256 MiB时间限制:5000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 假设有来自 n nn 个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri r_ir?i??.会议餐厅共有 m mm 张餐桌,每张餐桌可容纳 ci c_ic?i?? 个代表就餐.为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐. 试设计一个算法,给出满足要求的

【网络流24题】圆桌聚餐(最大流)

[网络流24题]圆桌聚餐(最大流) 题面 Cogs 题解 这道题很简单 首先每个单位的人数限制 直接从源点向单位连边,容量为人数 同样的, 每个桌子向汇点连边,容量为可以坐的人数 因为每个桌子只能够做一个该单位的人 所以,每个单位向桌子连边,容量为1 然后跑一边最大流求方案就行了 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath&

【网络流24题】圆桌聚餐

LOJ 6004 [网络流24题]圆桌聚餐 题面 假设有来自\(n\)个不同单位的代表参加一次国际会议.每个单位的代表数分别为\(r_i\).会议餐厅共有\(m\)张餐桌,每张餐桌可容纳\(c_i\)个代表就餐. 为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐. 试设计一个算法,给出满足要求的代表就餐方案. 题解 源点向每个单位连一条边,边权是该单位人数: 每个单位向各个餐桌连一条边,边权是1: 每个餐桌向汇点连一条边,边权是餐桌容纳人数. 如果最大流 < 总人数,则无解.若有

[网络流24题] 圆桌聚餐

729. [网络流24题] 圆桌聚餐 ★★   输入文件:roundtable.in   输出文件:roundtable.out   评测插件 时间限制:1 s   内存限制:128 MB   «问题描述: 假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为 ri(i=1,2,3...m), .会议餐厅共有n张餐桌,每张餐桌可容纳c i(i=1,2...n) 个代表就餐. 为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐.试设计一个算法, 给出满足要求的代表就

[cogs729] [网络流24题#5] 圆桌聚餐 [网络流,最大流,多重二分图匹配]

建图:从源点向单位连边,边权为单位人数,从单位向圆桌连边,边权为1,从圆桌向汇点连边,边权为圆桌容量. #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <queue> #includ

COGS729 圆桌聚餐

问题描述:假设有来自m 个不同单位的代表参加一次国际会议.每个单位的代表数分别为ri(i=1,2,3...m), .会议餐厅共有n张餐桌,每张餐桌可容纳c i(i=1,2...n) 个代表就餐.为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐.试设计一个算法,给出满足要求的代表就餐方案.«编程任务:对于给定的代表数和餐桌数以及餐桌容量,编程计算满足要求的代表就餐方案.«数据输入:由文件roundtable.in提供输入数据.文件第1行有2 个正整数m和n,m表示单位数,n表示餐桌

洛谷.3254.圆桌问题(最大流ISAP)

题目链接 日常水题 还是忍不住吐槽这题奇怪的评价 #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() //#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=450,M=5e4+5,INF=0x3f3f3f3f,MAXIN=

大神刷题表

9月27日 后缀数组:[wikioi3160]最长公共子串 dp:NOIP2001统计单词个数 后缀自动机:[spoj1812]Longest Common Substring II [wikioi3160]最长公共子串 [spoj7258]Lexicographical Substring Search 扫描线+set:[poj2932]Coneology 扫描线+set+树上删边游戏:[FJOI2013]圆形游戏 结论:[bzoj3706][FJ2014集训]反色刷 最小环:[poj1734

LibreOJ #101. 最大流

二次联通门 : LibreOJ #101. 最大流 本想着去这个OJ刷刷板子题 结果被这道最大流给坑了... 10^6的网络流.... 一开始随手写了个dinic 交上去50 有点懵..后又加了些奇怪的优化 还是50 把class封装去掉 恩, 变成70了 然后就没有然后了 TLE了一整页 后来知道要加当前弧优化才能过 就先去学. 学完后, 加上后 还是70分过不了..非常绝望啊.. /* LibreOJ #101. 最大流(50) Dinic + 当前弧优化 用class封装了起来 50分 *