码迷,mamicode.com
首页 > 其他好文 > 详细

【网络流24题】圆桌问题

时间:2020-02-19 13:07:48      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:fine   front   while   back   bfs   个人   struct   pop   head   

题目地址:https://www.luogu.com.cn/problem/P3254

分析&做法

  • 这是一道比较简单的【网络流24题】
  • 很容易想到二分图
  • 左边$M$个点代表$M$个单位,右边$N$个点代表每一个桌子,对于$M$个公司,每一个公司向所有桌子连边,因为一个公司在一个桌子上只能派一个人,所以边权为$1$
  • 源点$S$连向左边的$M$个点,边权为该单位的人数$ri$,意思是这个公司派出了$ri$个人
  • 右边的$N$个点连向汇点$T$,边权为该桌子的容量$ci$,意思是这个桌子最多坐$ci$个人
  • 这一切就顺理成章的想出来了,最大流就是满足条件下最多能就做的人数
  • 如果最大流等于总人数,则输出$1$,否则输出$0$
  • 至于输出方案,我的方法是最后枚举$M$个公司的$N$条出边,如果残留流量为$0$,就说明派了一个人到那个桌子上,输出就好了

代码

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#define maxN 500
#define maxM 100000
#define INF 2e9
using namespace std;

int N, M, S, T, Ans, Sum;

struct Edge {
    int nxt, dis, to;
} e[maxM];
int cnte = 1, head[maxN];
inline void Add(int i, int j, int k) {
    e[++cnte].dis = k, e[cnte].nxt = head[i], e[cnte].to = j, head[i] = cnte;
    e[++cnte].dis = 0, e[cnte].nxt = head[j], e[cnte].to = i, head[j] = cnte;
}
int dep[maxN];
bool bfs() {
    queue<int> Q;
    memset(dep, 0, sizeof(dep));
    dep[S] = 1, Q.push(S);
    while (!Q.empty()) {
        int u = Q.front();
        Q.pop();
        for (int v, i = head[u]; i; i = e[i].nxt) {
            if (e[i].dis && !dep[v = e[i].to]) {
                dep[v] = dep[u] + 1;
                Q.push(v);
            }
        }
    }
    return dep[T];
}
vector<int> p[maxN];
int dfs(int u, int in) {
    if (u == T)
        return in;
    int out = 0;
    for (int v, i = head[u]; i && in; i = e[i].nxt) {
        if (e[i].dis && dep[v = e[i].to] == dep[u] + 1) {
            int tmp = dfs(v, min(in, e[i].dis));
            if (tmp > 0 && 1 <= u && u <= M)
                p[u].push_back(v - M);
            e[i].dis -= tmp, e[i ^ 1].dis += tmp;
            in -= tmp, out += tmp;
        }
    }
    if (!out)
        dep[u] = 0;
    return out;
}
int main() {
    cin >> M >> N;
    S = N + M + 1, T = S + 1;
    for (int i = 1, r; i <= M; ++i) {
        cin >> r, Sum += r;
        Add(S, i, r);
    }
    for (int i = M + 1, c; i <= M + N; ++i) {
        cin >> c, Add(i, T, c);
        for (int j = 1; j <= M; ++j) {
            Add(j, i, 1);
        }
    }
    while (bfs()) Ans += dfs(S, INF);
    if (Ans == Sum)
        printf("1\n");
    else {
        printf("0\n");
        return 0;
    }
    for (int u = 1; u <= M; ++u) {
        for (int i = head[u]; i; i = e[i].nxt) {
            if (!e[i].dis)
                printf("%d ", e[i].to - M);
        }
        printf("\n");
    }
    return 0;
}

 

【网络流24题】圆桌问题

标签:fine   front   while   back   bfs   个人   struct   pop   head   

原文地址:https://www.cnblogs.com/blog-fgy/p/12330598.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!