• 增广路算法 (最大流问题)


    Edmonds-Karp算法:

    计算机科学中, Edmonds–Karp算法通过实现Ford–Fulkerson算法来计算网络中的最大流,其时间复杂度为O(V E2). 该算法由Yefim (Chaim) Dinic 在1970年最先提出并由Jack Edmonds和Richard Karp 在1972年独立发表。

    视频:Edmonds-Karp算法视频

    最大流问题的目标:把最多的物品从s运送到t,其它点都是中转站。

    算法思路:从0流开始不断增加流量,保持每次增加流量后都满足容量限制·斜对称性·流量平衡3个条件。

    增广路:残量网络中任何一条从s到t的有向道路都对应一条原图中的增广路。

    增广:只要求出增广路中所有残量的最小值d,把对应的所有边都加上d。

    最大流判断条件:当残量网络中不存在增广路,则当前流就是最大流。

    POJ 1459

    模板题!

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <stdlib.h>
     4 #include <time.h>
     5 #include <cmath>
     6 #include <cstdio>
     7 #include <string>
     8 #include <cstring>
     9 #include <vector>
    10 #include <queue>
    11 #include <stack>
    12 #include <set>
    13 
    14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
    15 #define INF 0x3f3f3f3f
    16 #define INFL 0x3f3f3f3f3f3f3f3f
    17 #define zero_(x,y) memset(x , y , sizeof(x))
    18 #define zero(x) memset(x , 0 , sizeof(x))
    19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
    20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
    21 using namespace std ;
    22 #define N 505
    23 
    24 const double PI = acos(-1.0);
    25 typedef long long LL ;
    26 
    27 int n, np, nc, m, ans;
    28 int Map[N][N], pre[N], que[N];
    29 bool vis[N];
    30 
    31 bool bfs(){
    32     int head, tail;
    33     zero(vis);
    34     head = tail = 1;
    35     que[tail++] = n;
    36     vis[n] = true;
    37     while(tail > head){
    38         int u = que[head ++];
    39         for(int i = 0; i <= n+1; i++){
    40             if(!vis[i] && Map[u][i]){
    41                 pre[i] = u;
    42                 if(i == n+1) return true;
    43                 que[tail ++] = i;
    44                 vis[i] = true;
    45             }
    46         }
    47     }
    48     return false;
    49 }
    50 
    51 void End(){
    52     int i, sum = INF;
    53     for(i = n + 1; i != n; i = pre[i])
    54         sum = min(sum, Map[pre[i]][i]);
    55     for(i = n + 1; i != n; i = pre[i]){
    56         Map[pre[i]][i] -= sum;
    57         Map[i][pre[i]] += sum;
    58     }
    59     ans += sum;
    60 }
    61 
    62 int main(){
    63     //freopen("in.txt","r",stdin);
    64     //freopen("out.txt","w",stdout);
    65     //ios_base::sync_with_stdio(false); cin.tie(0);
    66     int u, v, w;
    67     while(~scanf("%d%d%d%d", &n, &np, &nc, &m)){
    68         zero(Map);
    69         while(m--){
    70             while(getchar() != '(');
    71             scanf("%d,%d)%d", &u, &v, &w);
    72             Map[u][v] += w;
    73         }
    74         while(np--){
    75             while(getchar() != '(');
    76             scanf("%d)%d", &u, &w);
    77             Map[n][u] = w;
    78         }
    79         while(nc--){
    80             while(getchar() != '(');
    81             scanf("%d)%d", &u, &w);
    82             Map[u][n+1] = w;
    83         }
    84         ans = 0;
    85         while(bfs()) End();
    86         printf("%d
    ", ans);
    87     }
    88     return 0;
    89 }
    View Code

    POJ 3041

    题意:给定N*N矩阵,其中M个点,每次删除整行或者整列,求最小删除数;

    思路:将行看成是x集合的点,列看成是y集合的点,M个点为对应边,就变成了二分图的最大匹配问题,

       这样就方便的转化成了最大流问题,只要在图中加入一个源点,和一个汇点即可;

       用0-n-1存储行,n-(2*n-1)存储列,2*n存储源点,2n+1存储汇点;

     

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <stdlib.h>
     4 #include <time.h>
     5 #include <cmath>
     6 #include <cstdio>
     7 #include <string>
     8 #include <cstring>
     9 #include <vector>
    10 #include <queue>
    11 #include <stack>
    12 #include <set>
    13 
    14 #define c_false ios_base::sync_with_stdio(false); cin.tie(0)
    15 #define INF 0x3f3f3f3f
    16 #define INFL 0x3f3f3f3f3f3f3f3f
    17 #define zero_(x,y) memset(x , y , sizeof(x))
    18 #define zero(x) memset(x , 0 , sizeof(x))
    19 #define MAX(x) memset(x , 0x3f ,sizeof(x))
    20 #define swa(x,y) {LL s;s=x;x=y;y=s;}
    21 using namespace std ;
    22 #define N 1005
    23 
    24 const double PI = acos(-1.0);
    25 typedef long long LL ;
    26 
    27 int n, m, ans;
    28 int Map[N][N], pre[N], que[N];
    29 bool vis[N];
    30 
    31 bool bfs(){
    32     int head, tail;
    33     zero(vis);
    34     head = tail = 1;
    35     que[tail++] = 2*n;
    36     vis[2*n] = true;
    37     while(tail > head){
    38         int u = que[head ++];
    39         for(int i = 0; i <= 2*n+1; i++){
    40             if(!vis[i] && Map[u][i]){
    41                 pre[i] = u;
    42                 if(i == 2*n+1) return true;
    43                 que[tail ++] = i;
    44                 vis[i] = true;
    45             }
    46         }
    47     }
    48     return false;
    49 }
    50 
    51 void End(){
    52     int i, sum = INF;
    53     for(i = 2*n + 1; i != 2*n; i = pre[i])
    54         sum = min(sum, Map[pre[i]][i]);
    55     for(i = 2*n + 1; i != 2*n; i = pre[i]){
    56         Map[pre[i]][i] -= sum;
    57         Map[i][pre[i]] += sum;
    58     }
    59     ans += sum;
    60 }
    61 
    62 int main(){
    63     //freopen("in.txt","r",stdin);
    64     //freopen("out.txt","w",stdout);
    65     //ios_base::sync_with_stdio(false); cin.tie(0);
    66     int u, v;
    67     while(~scanf("%d%d", &n, &m)){
    68         zero(Map);
    69         for(int i = 0; i < m; i++){
    70             scanf("%d%d", &u, &v);
    71             Map[u-1][v-1+n] = 1;
    72             Map[2*n][u-1]   = 1;
    73             Map[n+v-1][(2*n)+1] = 1;
    74         }
    75         ans = 0;
    76         while(bfs()) End();
    77         printf("%d
    ", ans);
    78     }
    79     return 0;
    80 }
    View Code

     

  • 相关阅读:
    入手了一个南京电表厂MF16袖珍万用电表,哥测的不是电,是情怀
    40元淘来的香橙派 orange pi one 全志h3竟然可以安装桌面使用浏览器firefox上网
    https://blog.csdn.net/daaikuaichuan/article/details/83862311
    Arthas
    elect、poll、epoll优缺点
    jvm调优神器——arthas
    Mysql事物与二阶段提交
    全网最全一篇数据库MVCC详解,不全你打我
    冒泡排序和选择排序
    快速排序(过程图解)
  • 原文地址:https://www.cnblogs.com/yoyo-sincerely/p/5399446.html
Copyright © 2020-2023  润新知