zoukankan      html  css  js  c++  java
  • 【网络流24题】 5. 圆桌问题 题解

    题目链接(洛谷 P3254)

    题意

    有来自(m)个不同单位的代表参加一次国际会议。第(i)个单位派出了(r_i)个代表。

    会议的餐厅共有(n)张餐桌,第(i)张餐桌可容纳(c_i)个代表就餐。

    为了使代表们充分交流,希望从同一个单位来的代表不在同一个餐桌就餐。请给出一个满足要求的代表就餐方案。

    思路

    我们考虑从源点向每个单位连接一条容量为该单位人数的边,从每个桌子向汇点连接一条容量为该桌子人数的边,然后每个单位向每个桌子都连接一条容量为(1)的边(因为每张桌子上每个单位最多只能有一个人),然后跑最大流。如果最大流和总人数相同,则有解,否则无解。

    代码

    PS:Dinic写的太慢(dfs)会被卡QAQ

    /**
     * luogu P3254 https://www.luogu.com.cn/problem/P3254
     * Dinic
     **/
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    const int maxn = 1000;
    const int S = 0;
    const int T = maxn - 1;
    const int INF = 0x5f5f5f5f;
    
    struct Edge {
        int to, val, nxt;
    }e[maxn * maxn];
    
    int numedge, head[maxn], n, m, depth[maxn], ans, sum;
    
    inline void AddEdge(int from, int to, int val) {
        e[numedge].to = to;
        e[numedge].val = val;
        e[numedge].nxt = head[from];
        head[from] = numedge;
        numedge++;
    }
    
    inline void init() {
        memset(head, -1, sizeof(head));
    }
    
    inline bool bfs() {
        memset(depth, 0, sizeof(depth));
        depth[S] = 1;
        queue<int> q;
        q.push(S);
        while (!q.empty()) {
            int u = q.front();
            q.pop();
            for (int i = head[u]; ~i; i = e[i].nxt) {
                int to = e[i].to;
                if (!depth[to] && e[i].val > 0) {
                    depth[to] = depth[u] + 1;
                    q.push(to);
                }
            }
        }
        return depth[T] != 0;
    }
    
    int dfs(int u, int flow) {
        if (u == T || !flow) return flow;
        int sum = 0;
        for (int i = head[u]; ~i; i = e[i].nxt) {
            int to = e[i].to;
            if (depth[to] > depth[u] && e[i].val > 0) {
                int di = dfs(to, min(flow, e[i].val));
                if (di > 0) {
                    sum += di;
                    flow -= di;
                    e[i].val -= di;
                    e[i ^ 1].val += di;
                    // return di;
                }
            }
        }
        if (!sum) depth[u] = 0;
        return sum;
    }
    
    inline int Dinic() {
        int res = 0;
        while (bfs()) {
            int d;
            while ((d = dfs(S, INF)))
                res += d;
        }
        return res;
    }
    
    int main() {
        init();
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            int x;
            scanf("%d", &x);
            sum += x;
            AddEdge(S, i, x);
            AddEdge(i, S, 0);
        }
        for (int i = 1; i <= m; i++) {
            int x;
            scanf("%d", &x);
            AddEdge(i + n, T, x);
            AddEdge(T, i + n, 0);
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                AddEdge(i, j + n, 1);
                AddEdge(j + n, i, 0);
            }
        }
        ans = Dinic();
        if (ans == sum) {
            printf("1
    ");
            for (int i = 1; i <= n; i++) {
                for (int j = head[i]; ~j; j = e[j].nxt) {
                    int to = e[j].to;
                    if (to > n && e[j].val == 0) {
                        printf("%d ", to - n);
                    }
                }
                putchar('
    ');
            }
        }
        else {
            printf("0
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    39)自定义String类(没看)
    37)智能指针(就是自动delete空间)
    36)友元函数和重载操作符 (没看) 可以看视频
    35)类和结构体类比---this
    34)static 静态成员和静态成员函数
    33)new和delete关键字
    32)(典型)构造和析构 拷贝构造 小样例
    31)类中成员初始化
    30)构造函数的初始化列表
    29)深拷贝和浅拷贝
  • 原文地址:https://www.cnblogs.com/icysky/p/13623253.html
Copyright © 2011-2022 走看看