网络流应用 I



前言

被两个并不看正文的同学追着更新….emmmm…..
本文不写题意不写思路只给代码,一切内容都在以下PKU的课件中
(PS:膜拜神犇们的构图 orz)

  1. 综合
    http://acm.pku.edu.cn/summerschool/gw_netflow.pdf

Optimal Milking - POJ 2112

  #include <cstdio>
  #include <cstring>
  #include <algorithm>
  using namespace std;
  const int N = 250;
  const int inf = 0x3f3f3f3f;

  struct edge{
      int v, val, next;
      edge(int pv, int pval, int pnext): v(pv), val(pval), next(pnext) {}
      edge() {}
  };

  edge e[N*N*2];
  int  tot, head[N], pre[N], d[N], cur[N], gap[N];
  int  G[N][N];

  inline void init(){
      memset(head, -1, sizeof(head));
      tot = 0;
  }

  inline void addEdge(int u, int v, int val){
      e[tot] = edge(v, val, head[u]);
      head[u] = tot++;
      e[tot] = edge(u, 0, head[v]);
      head[v] = tot++;
  }

  void floyd(int n){
      for(int k = 1; k <= n; k++){
          for(int i = 1; i <= n; i++){
              for(int j = 1; j <= n; j++){
                  G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
              }
          }
      }
  }

  void build(int k, int c, int m, int maxdist){
      for(int i = k + 1; i <= k + c; i++)     addEdge(0, i, 1);
      for(int i = 1; i <= k; i++)             addEdge(i, k + c + 1, m);
      for(int i = k + 1; i <= k + c; i++){
          for(int j = 1; j <= k; j++){
              if(G[i][j] <= maxdist)          addEdge(i, j, 1);
          }
      }
  }

  int ISAP(int src, int des, int n){
      memcpy(cur, head, sizeof(head));
      memset(gap, 0, sizeof(gap));
      memset(d, 0, sizeof(d));
      int u = pre[src] = src;
      int sum = 0;
      gap[0] = n;
      while(d[src] < n){
          if(u == des){
              int v, aug = inf;
              for(u = pre[des], v = des; v != src; v = u, u = pre[u])     aug = min(aug, e[cur[u]].val);
              for(u = pre[des], v = des; v != src; v = u, u = pre[u]){
                  e[cur[u]].val -= aug;
                  e[cur[u]^1].val += aug;
              }
              sum += aug;
              continue;
          }

          bool flag = false;
          for(int& i = cur[u]; ~i; i = e[i].next){
              int v = e[i].v;
              if(d[u] == d[v] + 1 && e[i].val){
                  pre[v] = u;
                  u = v;
                  flag = true;
                  break;
              }
          }

          if(!flag){
              int mind = n;
              for(int i = head[u]; ~i; i = e[i].next){
                  int v = e[i].v;
                  if(e[i].val && d[v] < mind){
                      mind = d[v];
                      cur[u] = i;
                  }
              }

              if((--gap[d[u]]) == 0)    break;
              d[u] = mind + 1;
              gap[d[u]]++;
              u = pre[u];
          }
      }
      return sum;
  }

  int main(){
      int k, c, m;
      while(~scanf("%d%d%d", &k, &c, &m)){
          for(int i = 1; i <= k + c; i++){
              for(int j = 1; j <= k + c; j++){
                  scanf("%d", &G[i][j]);
                  if(G[i][j] == 0)    G[i][j] = inf;
              }
          }
          floyd(k + c);

          int l = 0, r = 60000, ans;
          while(l <= r){
              int mid = (l + r) >> 1;
              init();
              build(k, c, m, mid);
              if(ISAP(0, k + c + 1, k + c + 2) == c){
                  ans = mid;
                  r   = mid - 1;
              }else{
                  l   = mid + 1;
              }
          }
          printf("%d\n", ans);
      }
  }


ACM Computer Factory - POJ 3436

  #include <cstdio>
  #include <cstring>
  #include <vector>
  using namespace std;
  const int N = 50 + 15;
  const int M = 1e4 + 15;
  const int P = 10 + 15;
  const int inf = 0x3f3f3f3f;

  struct edge{
      int v, flow, cap, nxt;
      edge(int pv, int pflow, int pcap, int pnxt): v(pv), flow(pflow), cap(pcap), nxt(pnxt) {}
      edge() {}
  };

  int  d[N], head[N], gap[N], cur[N], pre[N];
  edge e[M << 1];
  int  tot;

  int from[N][P], to[N][P], val[N];
  vector<int> ansu, ansv, ansflow;

  inline void init(){
      memset(head, -1, sizeof(head));
      memset(d, 0, sizeof(d));
      memset(gap, 0, sizeof(gap));
      tot = 0;
      ansu.clear();
      ansv.clear();
      ansflow.clear();
  }

  void addEdge(int u, int v, int val){
      e[tot] = edge(v, 0, val, head[u]);
      head[u] = tot++;
      e[tot] = edge(u, val, val, head[v]);
      head[v] = tot++;
  }

  bool can(int i, int j, int p){
      for(int k = 0; k < p; k++){
          if(from[i][k] == 2)     continue;
          if(from[i][k] != to[j][k])  return false;
      }
      return true;
  }

  void buildG(int n, int p){
      for(int i = 0; i < n; i++){
          bool flag = true;
          for(int j = 0; j < p; j++){
              if(from[i][j] == 1){
                  flag = false;
                  break;
              }
          }
          if(flag)    addEdge(0, i + 1, inf);
      }
      for(int i = 0; i < n; i++){
          addEdge(i + 1, i + 1 + n, val[i]);
      }
      for(int i = 0; i < n; i++){
          bool flag = true;
          for(int j = 0; j < p; j++){
              if(to[i][j] == 0){
                  flag = false;
                  break;
              }
          }
          if(flag)    addEdge(i + 1 + n, n << 1 | 1, inf);
      }

      for(int i = 0; i < n; i++){
          for(int j = 0; j < n; j++){
              if(can(i, j, p)){
                  addEdge(j + n + 1, i + 1, inf);
              }
          }
      }
  }

  int ISAP(int n, int src, int des){
      memcpy(cur, head, sizeof(head));
      int sum = 0;
      int u = pre[src] = src;
      gap[0] = n;

      while(d[src] < n){
          if(u == des){
              int aug = inf, v;
              for(u = pre[des], v = des; v != src; v = u, u = pre[u])     aug = min(aug, e[cur[u]].cap - e[cur[u]].flow);
              for(u = pre[des], v = des; v != src; v = u, u = pre[u]){
                  e[cur[u]].flow   += aug;
                  e[cur[u]^1].flow -= aug;
              }
              sum += aug;
              continue;
          }

          bool flag = false;
          for(int& i = cur[u]; ~i; i = e[i].nxt){
              int v = e[i].v;
              if(d[u] == d[v] + 1 && e[i].cap - e[i].flow > 0){
                  pre[v] = u;
                  u = v;
                  flag = true;
                  break;
              }
          }

          if(!flag){
              int mind = n;
              for(int i = head[u]; ~i; i = e[i].nxt){
                  int v = e[i].v;
                  if(e[i].cap - e[i].flow > 0 && d[v] < mind){
                      mind = d[v];
                      cur[u] = i;
                  }
              }
              if((--gap[d[u]]) == 0)      break;
              d[u] = mind + 1;
              gap[d[u]]++;
              u = pre[u];
          }
      }
      return sum;
  }


  void getAns(int n){
      for(int i = 0; i < tot; i += 2){
          if(e[i].flow > 0){
              int u = e[i^1].v;
              int v = e[i].v;
              if(u > n && v <= n){
                  ansu.push_back(u - n);
                  ansv.push_back(v);
                  ansflow.push_back(e[i].flow);
              }
          }
      }
  }

  int main(){
      int p, n;
      while(~scanf("%d%d", &p, &n)){
          init();
          for(int i = 0; i < n; i++){
              scanf("%d", &val[i]);
              for(int j = 0; j < p; j++)      scanf("%d", &from[i][j]);
              for(int j = 0; j < p; j++)      scanf("%d", &to[i][j]);
          }
          buildG(n, p);

          int maxx = ISAP(2*n + 2, 0, 2*n + 1);
          getAns(n);
          printf("%d %d\n", maxx, ansu.size());
          for(int i = 0; i < ansu.size(); i++){
              printf("%d %d %d\n", ansu[i], ansv[i], ansflow[i]);
          }
      }
  }


PIGS - POJ 1149

  #include <cstdio>
  #include <cstring>
  #include <algorithm>
  using namespace std;
  const int N = 1e3 + 15;
  const int inf = 0x3f3f3f3f;

  struct edge{
      int v, val, next;
      edge(int pv, int pval, int pnext): v(pv), val(pval), next(pnext) {}
      edge() {}
  };

  edge e[N*N*2];
  int  tot, head[N], pre[N], d[N], cur[N], gap[N];
  int  val[N], mp[N];

  inline void init(){
      memset(head, -1, sizeof(head));
      memset(mp, -1, sizeof(mp));
      tot = 0;
  }

  inline void addEdge(int u, int v, int val){
      e[tot] = edge(v, val, head[u]);
      head[u] = tot++;
      e[tot] = edge(u, 0, head[v]);
      head[v] = tot++;
  }

  int ISAP(int src, int des, int n){
      memcpy(cur, head, sizeof(head));
      memset(gap, 0, sizeof(gap));
      memset(d, 0, sizeof(d));
      int u = pre[src] = src;
      int sum = 0;
      gap[0] = n;
      while(d[src] < n){
          if(u == des){
              int v, aug = inf;
              for(u = pre[des], v = des; v != src; v = u, u = pre[u])     aug = min(aug, e[cur[u]].val);
              for(u = pre[des], v = des; v != src; v = u, u = pre[u]){
                  e[cur[u]].val -= aug;
                  e[cur[u]^1].val += aug;
              }
              sum += aug;
              continue;
          }

          bool flag = false;
          for(int& i = cur[u]; ~i; i = e[i].next){
              int v = e[i].v;
              if(d[u] == d[v] + 1 && e[i].val){
                  pre[v] = u;
                  u = v;
                  flag = true;
                  break;
              }
          }

          if(!flag){
              int mind = n;
              for(int i = head[u]; ~i; i = e[i].next){
                  int v = e[i].v;
                  if(e[i].val && d[v] < mind){
                      mind = d[v];
                      cur[u] = i;
                  }
              }

              if((--gap[d[u]]) == 0)    break;
              d[u] = mind + 1;
              gap[d[u]]++;
              u = pre[u];
          }
      }
      return sum;
  }

  int main(){
      int n, m;
      while(~scanf("%d%d", &n, &m)){
          init();
          for(int i = 1; i <= n; i++)     scanf("%d", &val[i]);
          for(int i = 1; i <= m; i++){
              int k, dist;
              scanf("%d", &k);
              while(k--){
                  int tmp;
                  scanf("%d", &tmp);
                  if(mp[tmp] == -1){
                      mp[tmp] = i;
                      addEdge(0, mp[tmp], val[tmp]);
                  }else{
                      addEdge(mp[tmp], i, inf);
                      mp[tmp] = i;
                  }
              }
              scanf("%d", &dist);
              addEdge(i, m + 1, dist);
          }

          printf("%d\n", ISAP(0, m + 1, m + 2));
      }
  }