zoukankan      html  css  js  c++  java
  • srm537 div13 最小费用最大流

    看了很多人讲解的最小费用最大流,但是讲的都太不清楚了,感觉还是这个清楚

    http://www.strongczq.com/2012/03/srm537-div1-3-princexdominoes.html

    看了一个星期,把其中的各种变量都拆了出来,终于把最小费用最大流的各种细节明白了,

    我认为理解这个算法的还是理解剩余网络

      1 #include <iostream>
      2 #include <string>
      3 #include <vector>
      4 #include <cstdlib>
      5 #include <cmath>
      6 #include <map>
      7 #include <algorithm>
      8 #include <list>
      9 #include <ctime>
     10 #include <set>
     11 #include <string.h>
     12 #include <queue>
     13 using namespace std;
     14 
     15 int maxData = 0x3fffffff;
     16 
     17 int augment(int v, vector<int> pre, int cap, vector<vector<int> > &capacity,
     18         vector<vector<int> > &residual, vector<vector<int> > cost_graph,
     19         int& cost) {
     20     int u = pre[v];
     21     int r = residual[u][v] > 0 ? 1 : 0;
     22     int minCap;
     23     if (r == 0) {
     24         minCap = min(cap, capacity[u][v]);
     25     } else {
     26         minCap = min(cap, residual[u][v]);
     27     }
     28 
     29     if (u != 0) {
     30         minCap = augment(u, pre, minCap, capacity, residual, cost_graph, cost);
     31     }
     32     if (r == 0) {
     33         capacity[u][v] -= minCap;
     34         residual[v][u] += minCap;
     35     } else {
     36         capacity[v][u] += minCap;
     37         residual[u][v] -= minCap;
     38     }
     39     cost += (r == 0 ? cost_graph[u][v] : -cost_graph[v][u]) * minCap;
     40     return minCap;
     41 }
     42 
     43 int SPFA(int s, int des, vector<int> &pre, vector<vector<int> > &capacity,
     44         vector<vector<int> > &residual, vector<vector<int> > cost_graph) {
     45     int n = capacity.size();
     46     queue<int> myqueue;
     47     int i;
     48     vector<int> d(n, maxData); //将除源点以外的其余点的距离设置为无穷大
     49     d[s] = 0; //源点的距离为0
     50 
     51     for (i = 0; i < n; ++i) { //初始化前驱
     52         pre[i] = -1;
     53     }
     54     vector<bool> final(n, false); //记录顶点是否在队列中,SPFA算法可以入队列多次
     55 
     56     final[s] = true;
     57     myqueue.push(s);
     58     int topint;
     59     while (!myqueue.empty()) {
     60         topint = myqueue.front();
     61         myqueue.pop();
     62         final[topint] = false;
     63         for (i = 0; i < n; ++i) {
     64             if (d[i] > d[topint] + cost_graph[topint][i]
     65                     && capacity[topint][i] > 0) {
     66                 d[i] = d[topint] + cost_graph[topint][i];
     67                 pre[i] = topint;
     68                 if (!final[i]) { //判断是否在当前的队列中
     69                     final[i] = true;
     70                     myqueue.push(i);
     71                 }
     72             }
     73 
     74             if (d[i] > d[topint] - cost_graph[i][topint]
     75                     && residual[topint][i] > 0) {
     76                 d[i] = d[topint] - cost_graph[i][topint];
     77                 pre[i] = topint;
     78                 if (!final[i]) { //判断是否在当前的队列中
     79                     final[i] = true;
     80                     myqueue.push(i);
     81                 }
     82             }
     83         }
     84     }
     85 
     86     if (pre[des] == -1)
     87         return -1;
     88     return 1;
     89 }
     90 
     91 int maxFlow(int src, int des, vector<vector<int> > &capacity,
     92         vector<vector<int> > cost_graph) {
     93 
     94     int increasement = 0; //增广路径的值
     95     int n = capacity.size();
     96     vector<vector<int> > residual(n, vector<int>(n, 0)); //剩余网络
     97     vector<int> pre(n, -1); //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
     98     int cost = 0;
     99     while ((increasement = SPFA(src, des, pre, capacity, residual, cost_graph))
    100             != -1) {
    101         int cap = augment(des, pre, maxData, capacity, residual, cost_graph,cost);
    102     }
    103 
    104     return cost;
    105 }
    106 
    107 class PrinceXDominoes {
    108 public:
    109     int play(vector<string> dominoes) {
    110         int n = dominoes.size();
    111         int total = 0;
    112         int useless=0;
    113         vector<vector<int> > path(n + 2, vector<int>(n + 2, 0));
    114         vector<vector<int> > cost_graph(n + 2, vector<int>(n + 2, 1));
    115         vector<vector<bool> > connected(n, vector<bool>(n, false));
    116         vector<int> red_minus_black(n, 0);
    117         int i, j;
    118         for (int i = 0; i < n; ++i) {
    119             connected[i][i] = true;
    120         }
    121         for (int i = 0; i < n + 2; ++i) {
    122             cost_graph[i][i] = 0;
    123         }
    124         for (i = 0; i < n; i++) {
    125             for (j = 0; j < n; j++) {
    126                 if (dominoes[i][j] != '.') {
    127                     int tmp = dominoes[i][j] - 'A' + 1;
    128                     path[i + 1][j + 1] = tmp - 1;
    129                     total = total + tmp;
    130                     red_minus_black[i] += tmp;
    131                     red_minus_black[j] -= tmp;
    132                     connected[i][j] = true;
    133                 }
    134             }
    135         }
    136 
    137         for (int k = 0; k < n; ++k)
    138             for (int i = 0; i < n; ++i)
    139                 for (int j = 0; j < n; ++j) {
    140                     connected[i][j] = connected[i][j]
    141                             || (connected[i][k] && connected[k][j]);
    142                 }
    143 
    144         for (int i = 0; i < n; ++i)
    145             for (int j = 0; j < n; ++j)
    146                 if (!connected[i][j]) {
    147                     return -1;
    148                 }
    149 
    150         for (int i = 0; i < n; ++i) { //初始化src和des点
    151             if (red_minus_black[i] > 0) {
    152                 path[0][i + 1] = red_minus_black[i];
    153                 useless +=red_minus_black[i];
    154             } else {
    155                 path[i + 1][n + 1] = -red_minus_black[i];
    156                 useless -=red_minus_black[i];
    157             }
    158         }
    159         int res = maxFlow(0, n + 1, path, cost_graph);
    160         for(int i=0;i<n+2;i++){
    161                 if(path[0][i]!=0){
    162                     return -1;
    163                 }
    164         }
    165 
    166             return total - res+2*useless;
    167     }
    168 
    169 };
  • 相关阅读:
    原生js系列 删除元素
    事件绑定的几种方式
    js的五种输出方式
    三、浏览器事件处理机制--事件循环(event loop)
    二、事件流、事件代理
    一、事件的分类
    js数据类型转换
    html锚点
    观察者模式
    策略模式
  • 原文地址:https://www.cnblogs.com/kakamilan/p/2644315.html
Copyright © 2011-2022 走看看