• POJ3436 ACM Computer Factory(最大流)


    题目链接

    分析:

    题意很难懂。

    大体是这样的:给每个点的具体情况,1.容量 2。进入状态 3.出去状态。求最大流。

    因为有很多点,所以如果一个点的出去状态满足另一个点的进入状态,则这两个点可以连一条边。容量为两者容量的较小值。

    再建立一个超源、一个超汇。让超源与所有进入状态全为0或者不全为0但只包含0和2的点连边,同时让所有出去状态全部为1的与超汇连边。

    然后求最大流.

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    
    using namespace std;
    
    const int maxn = 60;
    const int INF = (1<<29);
    
    int in[maxn][12], cap[maxn][maxn], n, flow[maxn][maxn];
    
    int EK(int s, int t) {
        queue<int> q;
        int p[maxn], a[maxn];
    
        int f = 0;
    
        memset(flow, 0, sizeof(flow));
    
        while(true) {
            memset(a, 0, sizeof(a));
            a[s] = INF;
            q.push(s);
            while(!q.empty()) {
                int u = q.front(); q.pop();
                for(int v = 0; v < n; v++) if(!a[v] && cap[u][v] > flow[u][v]) {
                    p[v] = u; q.push(v);
                    a[v] = min(a[u], cap[u][v]-flow[u][v]);
                }
            }
    
            if(a[t] == 0) break;
            for(int u=t; u != s; u = p[u]) {
                flow[p[u]][u] += a[t];
                flow[u][p[u]] -= a[t];
            }
            f += a[t];
        }
        return f;
    }
    
    int main() {
        int p;
    
        while(scanf("%d%d", &p, &n) == 2) {
    
            memset(cap, 0, sizeof(cap));
    
            for(int i=0; i<2*p+1; i++) {        //初始化超源,超汇
                in[0][i] = 0;
                in[n+1][i] =1;
            }
    
            for(int i=1; i<=n; i++) {           //输入数据
                for(int j=0; j<2*p+1; j++) {
                    scanf("%d", &in[i][j]);
                }
            }
    
            n+=2;                               //点数+2
    
            for(int i=0; i<n; i++) {            //将可以连通的点,记录,算出每条边的容量
                for(int j=0; j<n; j++) {
                    if(i == j) continue;
    
                    bool flag = true;
                    for(int k=1; k<=p; k++) {
                        if( !((in[j][k] == 2) || (in[i][k+p] == in[j][k])) ) {
                            flag = false;
                        }
                    }
                    if(flag && i == 0) cap[i][j] = in[j][0];
                    else if(flag && j == n-1) cap[i][j] = in[i][0];
                    else if(flag) cap[i][j] += min(in[i][0], in[j][0]);
                }
            }
    
            printf("%d ", EK(0, n-1));          //增广路算法
    
            int cnt = 0;                        //计数
            for(int i=1; i<n-1; i++) {
                for(int j=1; j<n-1; j++) {
                    if(flow[i][j] > 0) cnt++;
                }
            }
            printf("%d
    ", cnt);
    
            for(int i=1; i<n-1; i++) {          //输出
                for(int j=1; j<n-1; j++) {
                    if(flow[i][j] > 0) printf("%d %d %d
    ", i, j, flow[i][j]);
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    Spring笔记:常用xml标签和属性 山上下了雪
    Spring笔记:Hello World 山上下了雪
    Spring笔记:bean的自动装配 山上下了雪
    IntelliJ IDEA 2020.3.3 x64破解到2099年
    每日长进计划
    idea测试类中的测试方法没有运行按钮
    删除所有的phpfpm进程命令
    高质量编程
    单例模式也能玩出花
    宝塔Linux面板安装命令
  • 原文地址:https://www.cnblogs.com/tanhehe/p/3256793.html
Copyright © 2020-2023  润新知