• 「网络流24题」圆桌问题


    传送门:>Here<

    题意:M个单位每个单位有a[i]个人。现在他们要一起聚餐。共有N张餐桌,每张餐桌容量为c[i],要求每个单位内部的人不能做同一张餐桌。输出一种分配方案(不行则输出0)

    思路分析

      一眼题解都没瞟就A了 说明最大流还是没有白学 233

      一看这题容量就不能全是1了,肯定跟餐桌容量与单位人数有关。不妨先从源点连边到每个单位,容量就是这个单位的人数。每个单位连容量为1的边到各个餐桌。各个餐桌再连边到汇点,容量为餐桌容量。在这里,餐桌到汇点的容量用来约束每个餐桌的人数上限,而中间的容量为1的边则约束每个单位到每个餐桌最多一个人。源点到各个单位的容量就约束了每个单位的人数了。因此问题就迎刃而解。

      因此每一条流量为1的流代表着一个人,从一个单位发散出去的流就是这个单位的人的分配了。判断是否有解也就是判断最大流是否等于人数之和

    Code

      none!

    /*By DennyQi*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef long long ll;
    const int MAXN = 100010;
    const int MAXM = 270010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar(); return x * w;
    }
    int N,M,S,T,x,ans,tot_num;
    int first[MAXM],nxt[MAXM],to[MAXM],cap[MAXM],flow[MAXM],num_edge=-1;
    int level[MAXN],cur[MAXN];
    queue <int> q;
    inline void add(int u, int v, int c, int f){
        to[++num_edge] = v;
        cap[num_edge] = c;
        flow[num_edge] = f;
        nxt[num_edge] = first[u];
        first[u] = num_edge;
    }
    inline bool BFS(){
        memset(level, 0, sizeof(level));
        while(!q.empty()) q.pop();
        q.push(S);
        level[S] = 1;
        int u,v;
        while(!q.empty()){
            u = q.front(); q.pop();
            for(int i = first[u]; i != -1; i = nxt[i]){
                v = to[i];
                if(!level[v] && cap[i]-flow[i] > 0){
                    level[v] = level[u] + 1;
                    q.push(v);
                }
            }
        }
        return level[T]!=0;
    }
    int DFS(int u, int a){
        if(u == T || a == 0) return a;
        int ans = 0, _f, v;
        for(int& i = cur[u]; i != -1; i = nxt[i]){
            v = to[i];
            if(level[u]+1 == level[v] && cap[i]-flow[i] > 0){
                _f = DFS(v, Min(a, cap[i]-flow[i]));
                ans += _f, a -= _f;
                flow[i] += _f, flow[i^1] -= _f;
                if(a == 0) break;
            }
        }
        return ans;
    }
    inline void Dinic(){
        ans = 0;
        while(BFS()){
            for(int i = 1; i <= T; ++i) cur[i] = first[i];
            ans += DFS(S, INF);
        }
    }
    int main(){
    //    freopen(".in","r",stdin);
        M=r,N=r;
        memset(first,-1,sizeof(first));
        S = N+M+2, T = N+M+3;
        for(int i = 1; i <= M; ++i){
            x=r;
            tot_num += x;
            add(S, i, x, 0);
            add(i, S, 0, 0);
            for(int j = 1; j <= N; ++j){
                add(i, j+M, 1, 0);
                add(j+M, i, 0, 0);
            }
        }
        for(int i = 1; i <= N; ++i){
            x=r;
            add(i+M, T, x, 0);
            add(T, i+M, 0, 0);
        }
        Dinic();
        if(ans != tot_num){
            printf("0
    ");
            return 0;
        }
        printf("1
    ");
        for(int i = 1; i <= M; ++i){
            for(int j = first[i]; j != -1; j = nxt[j]){
                if(cap[j]-flow[j] == 0 && cap[j] == 1){
                    printf("%d ", to[j]-M);
                }
            }
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    回归cnblog
    第一篇博文
    apache 配置网站目录,虚拟目录,新端口
    linux 虚拟机设置IP访问外网
    Volist标签 key值的使用
    php header调试,yii2打log
    Yii2 框架下bootstrap 弹窗预览视频等~
    几个简单的css设置问题:div居中,ul li不换行 ,内容超出自动变省略号等
    鼠标右键弹窗(实现重命名等)的设计
    HTML5 Canvas绘图系列之一:圆弧等基础图形的实现
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9429164.html
Copyright © 2020-2023  润新知