zoukankan      html  css  js  c++  java
  • POJ1149最大流

    难度在于建图,剩下的就是求最大流问题了。

    贴上我的实现代码

    //题目的难度在于如何建图,将每一个客户当做点,另外添加一个源点s和汇点t,每个客户点建一条有向边指向汇点t,容量为该客户要购买的猪的数量;
    //若客户i是猪圈j的第一个访问者,则从源点s建一条边指向节点i,容量为猪圈的初始猪数,若客户i不是猪圈j的第一个客户,而该猪圈的上一个客户(pre数组记录)是
    //x,那么从x建一条边指向i, 容量为正无穷,支持建图完成,剩下只需算出s到t的最大流即可,以下用EK算法实现; 
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    const int MAXN = 1001;
    const int N = 101;
    const int MAX = 0x7FFFFFFF;
    int c[N][N], path[N], pre[MAXN], flow[N]; //pre数组记录某猪圈的前一个访问者,建图需要 
    queue<int>Q;
    int Edmonds_Karp(int s, int t) {
      int sum = 0;
      int u, v;
      while (1) {
          memset(path, -1, sizeof(path));
          while (!Q.empty())
            Q.pop();
        flow[s] = MAX;
        Q.push(s);
        while (!Q.empty() && path[t] == -1) {
             u = Q.front(); Q.pop();
             for (v = 0; v <= t; v++) {
               if (c[u][v] && path[v] == -1) {
                 path[v] = u;
                 flow[v] = flow[u] < c[u][v] ? flow[u] : c[u][v];
                 Q.push(v);
               } 
             }
        }
        if (path[t] != -1) {
          sum += flow[t];
          v = t;
          while (v != s) {
              c[path[v]][v] -= flow[t];
              c[v][path[v]] += flow[t];
              v = path[v];
          }
        } else {
          break;
        }
      }
      return sum;
    }
    
    int main()
    {
      int n1, k, order, i, j, n, m;
      int val[MAXN];
      while (scanf("%d%d", &m, &n) != EOF) {
          memset(c, 0, sizeof(c));
          memset(pre, 0, sizeof(pre));
          //以下为读取数据并建图
        for (i = 1; i <= m; i++)
            scanf("%d", &val[i]);
          for (i = 1; i <= n; i++) {
            scanf("%d", &n1);
            for (j = 0; j < n1; j++) {
                scanf("%d", &order);
                if (!pre[order]) {
                    c[0][i] += val[order]; 
                }else {
                    c[pre[order]][i] = MAX;
                }
                pre[order] = i;
            }
            scanf("%d", &k);
            c[i][n+1] = k; 
          }
          //求最大流 
          int sum = Edmonds_Karp(0, n+1);
          printf ("%d\n", sum);
      }
      return 0;
    }
  • 相关阅读:
    Lab IGMP
    IGMP知识要点
    15、通过例子讲解逻辑地址转换为物理地址的基本过程
    14、一个程序从开始运行到结束的完整过程,你能说出来多少?
    13、进程状态的切换你知道多少?
    12、虚拟技术你了解吗?
    11、动态分区分配算法有哪几种?可以分别说说吗?
    线程池
    10、内存交换和覆盖有什么区别?
    9、如果系统中具有快表后,那么地址的转换过程变成什么样了?
  • 原文地址:https://www.cnblogs.com/Patrickcxt/p/3226648.html
Copyright © 2011-2022 走看看