zoukankan      html  css  js  c++  java
  • 模板汇总——网络流

    1.  最大流

    const int N = 200;
    const int M = N*N;
    int head[N], deep[N], cur[N];
    int w[M], to[M], nx[M];
    int tot;
    void add(int u, int v, int val){
        w[tot]  = val; to[tot] = v;
        nx[tot] = head[u]; head[u] = tot++;
    
        w[tot] = 0; to[tot] = u;
        nx[tot] = head[v]; head[v] = tot++;
    }
    int bfs(int s, int t){
        queue<int> q;
        memset(deep, 0, sizeof(deep));
        q.push(s);
        deep[s] = 1;
        while(!q.empty()){
            int u = q.front();
            q.pop();
            for(int i = head[u]; ~i; i = nx[i]){
                if(w[i] > 0 && deep[to[i]] == 0){
                    deep[to[i]] = deep[u] + 1;
                    q.push(to[i]);
                }
            }
        }
        return deep[t] > 0;
    }
    int Dfs(int u, int t, int flow){
        if(u == t) return flow;
        for(int &i = cur[u]; ~i; i = nx[i]){
            if(deep[u]+1 == deep[to[i]] && w[i] > 0){
                int di = Dfs(to[i], t, min(w[i], flow));
                if(di > 0){
                    w[i] -= di, w[i^1] += di;
                    return di;
                }
            }
        }
        return 0;
    }
    
    int Dinic(int s, int t){
        int ans = 0, tmp;
        while(bfs(s, t)){
            for(int i = 0; i <= t; i++) cur[i] = head[i];
            while(tmp = Dfs(s, t, inf)) ans += tmp;
        }
        return ans;
    }
    void init(){
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    View Code

    2. 二分图最优匹配

     1 const int N = 210;
     2 int val[N][N];
     3 LL lx[N], ly[N], slack[N];
     4 int linky[N];
     5 LL pre[N];
     6 bool vis[N], visx[N],visy[N];
     7 void bfs(int k){
     8     LL px, py = 0,yy = 0, d;
     9     memset(pre, 0, sizeof(LL) * (n+2));
    10     memset(slack, inf, sizeof(LL) * (n+2));
    11     linky[py]=k;
    12     do{
    13         px = linky[py],d = INF, vis[py] = 1;
    14         for(int i = 1; i <= n; i++)
    15             if(!vis[i]){
    16                 if(slack[i] > lx[px] + ly[i] - val[px][i])
    17                     slack[i] = lx[px] + ly[i] -val[px][i], pre[i]=py;
    18                 if(slack[i]<d) d=slack[i],yy=i;
    19             }
    20         for(int i = 0; i <= n; i++)
    21             if(vis[i]) lx[linky[i]] -= d, ly[i] += d;
    22             else slack[i] -= d;
    23         py = yy;
    24     }while(linky[py]);
    25     while(py) linky[py] = linky[pre[py]] , py=pre[py];
    26 }
    27 void KM(){
    28     memset(lx, 0, sizeof(int)*(n+2));
    29     memset(ly, 0, sizeof(int)*(n+2));
    30     memset(linky, 0, sizeof(int)*(n+2));
    31     for(int i = 1; i <= n; i++)
    32         memset(vis, 0, sizeof(bool)*(n+2)), bfs(i);
    33 }
    34 void input(){
    35     for(int i = 1; i <= n; i++){
    36         for(int j = 1; j <= n; j++)
    37             scanf("%d", &val[i][j]);
    38 }
    39 int main(){
    40     input();
    41     KM();
    42     LL ans = 0;
    43     for(int i = 1; i <= n; ++i)
    44         ans += lx[i] + ly[i];
    45     printf("%lld
    ", ans);    
    46     return 0;
    47 }
    View Code

    结果是 尽可能多匹配情况下的 最大值, 如果需要求最小值, 在input 的时候将值取反, 最后输出的答案的时候也要取反。

     3.最小花费最大流

    KM+spfa 

    const int N = 1000;
    const int M = N * N;
    int head[N], to[M], ct[M], w[M], nt[M];
    int d[N], vis[N];
    int pre[N], id[N];
    int tot;
    
    void add(int u, int v, int flow, int cost){
        to[tot] = v; ct[tot] = cost;
        w[tot] = flow; nt[tot] = head[u]; head[u] = tot++;
    
        to[tot] = u; ct[tot] = -cost;
        w[tot] = 0; nt[tot] = head[v]; head[v] = tot++;
    }
    void init(){
        memset(head, -1, sizeof(head));
        tot = 0;
    }
    int spfa(int s, int t){
        queue<int> q;
        memset(d, inf, sizeof(d));
        memset(vis, 0, sizeof(vis));
        memset(pre, -1, sizeof(pre));
        d[s] = 0;
        q.push(s);
        while(!q.empty()){
            int u = q.front(); q.pop();
            vis[u] = 0;
            for(int i = head[u]; ~i; i = nt[i]){
                if(w[i] > 0 && d[to[i]] > d[u] + ct[i]){
                    d[to[i]] = d[u] + ct[i];
                    pre[to[i]] = u;
                    id[to[i]] = i;
                    if(!vis[to[i]]){
                        vis[to[i]] = 1;
                        q.push(to[i]);
                    }
                }
            }
    
        }
        return d[t] < inf;
    }
    int MinCostFlow(int s, int t){
        int Mi = inf;
        int sum = 0;
        int tt = 0;
        while(spfa(s, t)){
            Mi = inf;
            for(int i = t; i != s; i = pre[i])
                Mi = min(Mi, w[id[i]]);
            for(int i = t; i != s; i = pre[i]){
                w[id[i]] -= Mi;
                w[id[i]^1] += Mi;
            }
            tt += Mi;
            sum += d[t] * Mi;
        }
        return sum;
    }
    View Code

     

    如果需要最大的花费, 建边的时候将值取反就了。

    4.上下界网络流

    无源汇有上下界限制的网络流

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define max3(a,b,c) max(a,max(b,c))
     12 #define min3(a,b,c) min(a,min(b,c))
     13 #define _S(X) cout << x << ' ';
     14 #define __S(x) cout << x << endl;
     15 typedef pair<int,int> pll;
     16 const int INF = 0x3f3f3f3f;
     17 const LL mod =  (int)1e9+7;
     18 const int N = 20100;
     19 const int _M = 500100;
     20 int head[N];
     21 int M[N];
     22 int w[_M], to[_M], nx[_M], id[_M];
     23 int B[_M];
     24 int n, m, _u, _v, _w;
     25 int tot, s, t, ss, tt;
     26 int deep[N], cur[N];
     27 void add(int u, int v, int val){
     28     w[tot]  = val;
     29     to[tot] = v;
     30     nx[tot] = head[u];
     31     head[u] = tot++;
     32 }
     33 
     34 void init(){
     35     memset(head, -1, sizeof(int)*(n+3));
     36     memset(M, 0, sizeof(int)*(n+3));
     37     tot = 0;
     38     s = 1;
     39     t = n;
     40     ss = n + 1;
     41     tt = n + 2;
     42 }
     43 
     44 int bfs(int s, int t){
     45     queue<int> q;
     46     memset(deep, 0, sizeof(int)*(n+3));
     47     q.push(s);
     48     deep[s] = 1;
     49     while(!q.empty()){
     50         int u = q.front();
     51         q.pop();
     52         for(int i = head[u]; ~i; i = nx[i]){
     53             if(w[i] > 0 && deep[to[i]] == 0){
     54                 deep[to[i]] = deep[u] + 1;
     55                 q.push(to[i]);
     56             }
     57         }
     58     }
     59     if(deep[t] > 0) return 1;
     60     return 0;
     61 }
     62 int Dfs(int u, int t, int flow){
     63     if(u == t) return flow;
     64     for(int &i = cur[u]; ~i; i = nx[i]){
     65         if(deep[u]+1 == deep[to[i]] && w[i] > 0){
     66             int di = Dfs(to[i], t, min(w[i], flow));
     67             if(di > 0){
     68                 w[i] -= di, w[i^1] += di;
     69                 return di;
     70             }
     71         }
     72     }
     73     return 0;
     74 }
     75 int Dinic(int s, int t){
     76     int ans = 0, tmp;
     77     while(bfs(s, t)){
     78         for(int i = 1; i <= n+2; i++) cur[i] = head[i];
     79         while(tmp = Dfs(s, t, INF)) ans += tmp;
     80     }
     81     return ans;
     82 }
     83 int main(){
     84     while(~scanf("%d%d", &n, &m)){
     85         init();
     86         int b, c;
     87         for(int i = 1; i <= m; i++){
     88             scanf("%d%d%d%d", &_u, &_v, &b, &c);
     89             id[i] = tot; B[i] = b;
     90             add(_u,_v,c-b); add(_v,_u,0);
     91             M[_u] -= b; M[_v] += b;
     92         }
     93         int sum = 0;
     94         for(int i = 1; i <= n; i++){
     95             if(M[i] > 0) add(ss, i, M[i]), add(i, ss, 0), sum += M[i];
     96             if(M[i] < 0) add(i, tt, -M[i]), add(tt, i, 0);
     97         }
     98         int ans = Dinic(ss, tt);
     99         if(ans == sum){
    100             puts("YES");
    101             for(int i = 1; i <= m; i++)
    102                 printf("%d
    ",w[id[i]^1] + B[i]);
    103         }
    104         else puts("NO");
    105     }
    106     return 0;
    107 }
    View Code

    有源汇有上下界最大流

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define max3(a,b,c) max(a,max(b,c))
     12 #define min3(a,b,c) min(a,min(b,c))
     13 #define _S(X) cout << x << ' ';
     14 #define __S(x) cout << x << endl;
     15 typedef pair<int,int> pll;
     16 const int INF = 0x3f3f3f3f;
     17 const LL mod =  (int)1e9+7;
     18 const int N = 1000;
     19 const int _M = 50010;
     20 int head[N];
     21 int M[N];
     22 int w[_M], to[_M], nx[_M];
     23 int n, m, _u, _v, _w;
     24 int tot, s, t, ss, tt;
     25 int deep[N], cur[N];
     26 void add(int u, int v, int val){
     27     w[tot]  = val;
     28     to[tot] = v;
     29     nx[tot] = head[u];
     30     head[u] = tot++;
     31 }
     32 
     33 void init(){
     34     memset(head, -1, sizeof(int)*(n+3));
     35     memset(M, 0, sizeof(int)*(n+3));
     36     tot = 0;
     37     ss = n + 1;
     38     tt = n + 2;
     39 }
     40 
     41 int bfs(int s, int t){
     42     queue<int> q;
     43     memset(deep, 0, sizeof(int)*(n+3));
     44     q.push(s);
     45     deep[s] = 1;
     46     while(!q.empty()){
     47         int u = q.front();
     48         q.pop();
     49         for(int i = head[u]; ~i; i = nx[i]){
     50             if(w[i] > 0 && deep[to[i]] == 0){
     51                 deep[to[i]] = deep[u] + 1;
     52                 q.push(to[i]);
     53             }
     54         }
     55     }
     56     if(deep[t] > 0) return 1;
     57     return 0;
     58 }
     59 int Dfs(int u, int t, int flow){
     60     if(u == t) return flow;
     61     for(int &i = cur[u]; ~i; i = nx[i]){
     62         if(deep[u]+1 == deep[to[i]] && w[i] > 0){
     63             int di = Dfs(to[i], t, min(w[i], flow));
     64             if(di > 0){
     65                 w[i] -= di, w[i^1] += di;
     66                 return di;
     67             }
     68         }
     69     }
     70     return 0;
     71 }
     72 int Dinic(int s, int t){
     73     int ans = 0, tmp;
     74     while(bfs(s,t)){
     75         for(int i = 1; i <= n+2; i++) cur[i] = head[i];
     76         while(tmp = Dfs(s, t, INF)) ans += tmp;
     77     }
     78     return ans;
     79 }
     80 int main(){
     81     while(~scanf("%d%d", &n, &m)){
     82         init();
     83         scanf("%d%d", &s, &t);
     84         int b, c;
     85         for(int i = 1; i <= m; i++){
     86             scanf("%d%d%d%d", &_u, &_v, &b, &c);
     87             add(_u,_v,c-b); add(_v,_u,0);
     88             M[_u] -= b; M[_v] += b;
     89         }
     90         int sum = 0;
     91         for(int i = 1; i <= n; i++){
     92             if(M[i] > 0) add(ss, i, M[i]), add(i, ss, 0), sum += M[i];
     93             if(M[i] < 0) add(i, tt, -M[i]), add(tt, i, 0);
     94         }
     95         add(t,s,INF);
     96         add(s,t,0);
     97         int ans = Dinic(ss, tt);
     98         if(ans == sum){
     99             ans = w[--tot];
    100             w[tot] = 0; w[--tot] = 0;
    101             ans += Dinic(s, t);
    102             printf("%d
    ", ans);
    103         }
    104         else puts("please go home to sleep");
    105     }
    106     return 0;
    107 }
    View Code

    有源汇有上下界最小流

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define max3(a,b,c) max(a,max(b,c))
     12 #define min3(a,b,c) min(a,min(b,c))
     13 #define _S(X) cout << x << ' ';
     14 #define __S(x) cout << x << endl;
     15 typedef pair<int,int> pll;
     16 const int INF = 0x3f3f3f3f;
     17 const LL mod =  (int)1e9+7;
     18 const int N = 50100;
     19 const int _M = 350010;
     20 int head[N];
     21 int M[N];
     22 int w[_M], to[_M], nx[_M];
     23 int n, m, _u, _v, _w;
     24 int tot, s, t, ss, tt;
     25 int deep[N], cur[N];
     26 void add(int u, int v, int val){
     27     w[tot]  = val;
     28     to[tot] = v;
     29     nx[tot] = head[u];
     30     head[u] = tot++;
     31 }
     32 
     33 void init(){
     34     memset(head, -1, sizeof(int)*(n+3));
     35     memset(M, 0, sizeof(int)*(n+3));
     36     tot = 0;
     37     ss = n + 1;
     38     tt = n + 2;
     39 }
     40 
     41 int bfs(int s, int t){
     42     queue<int> q;
     43     memset(deep, 0, sizeof(int)*(n+3));
     44     q.push(s);
     45     deep[s] = 1;
     46     
     47     while(!q.empty()){
     48         int u = q.front();
     49         q.pop();
     50         for(int i = head[u]; ~i; i = nx[i]){
     51             if(w[i] > 0 && deep[to[i]] == 0){
     52                 deep[to[i]] = deep[u] + 1;
     53                 q.push(to[i]);
     54             }
     55         }
     56     }
     57     if(deep[t] > 0) return 1;
     58     return 0;
     59 }
     60 int Dfs(int u, int t, int flow){
     61     if(u == t) return flow;
     62     for(int &i = cur[u]; ~i; i = nx[i]){
     63         if(deep[u]+1 == deep[to[i]] && w[i] > 0){
     64             int di = Dfs(to[i], t, min(w[i], flow));
     65             if(di > 0){
     66                 w[i] -= di, w[i^1] += di;
     67                 return di;
     68             }
     69         }
     70     }
     71     return 0;
     72 }
     73 int Dinic(int s, int t){
     74     int ans = 0, tmp;
     75     while(bfs(s,t)){
     76         for(int i = 1; i <= n+2; i++) cur[i] = head[i];
     77         while(tmp = Dfs(s, t, INF)) ans += tmp;
     78     }
     79     return ans;
     80 }
     81 int main(){
     82     while(~scanf("%d%d", &n, &m)){
     83         init();
     84         scanf("%d%d", &s, &t);
     85         int b, c;
     86         for(int i = 1; i <= m; i++){
     87             scanf("%d%d%d%d", &_u, &_v, &b, &c);
     88             add(_u,_v,c-b); add(_v,_u,0);
     89             M[_u] -= b; M[_v] += b;
     90         }
     91         int sum = 0;
     92         for(int i = 1; i <= n; i++){
     93             if(M[i] > 0) add(ss, i, M[i]), add(i, ss, 0), sum += M[i];
     94             if(M[i] < 0) add(i, tt, -M[i]), add(tt, i, 0);
     95         }
     96         add(t,s,INF);
     97         add(s,t,0);
     98         int ans = Dinic(ss, tt);
     99         if(ans == sum){
    100             ans = w[--tot];
    101             w[tot] = 0; w[--tot] = 0;
    102             ans -= Dinic(t, s);
    103             printf("%d
    ", ans);
    104         }
    105         else puts("please go home to sleep");
    106     }
    107     return 0;
    108 }
    View Code

    5.最大密度子图

    (可选出合法的节点)

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 using namespace std;
      5 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      6 #define LL long long
      7 #define ULL unsigned LL
      8 #define fi first
      9 #define se second
     10 #define pb push_back
     11 #define lson l,m,rt<<1
     12 #define rson m+1,r,rt<<1|1
     13 #define max3(a,b,c) max(a,max(b,c))
     14 #define min3(a,b,c) min(a,min(b,c))
     15 typedef pair<int,int> pll;
     16 const LL INF = 0x3f3f3f3f3f3f3f3f;
     17 const int inf = 0x3f3f3f3f;
     18 const LL mod =  (int)1e9+7;
     19 const int N = 120;
     20 const int M = 10000;
     21 double eps = 1e-6;
     22 int head[N], deep[N], cur[N];
     23 int u[M], v[M];
     24 int vis[N], d[N];
     25 double w[M]; int to[M], nx[M];
     26 int n, m, tot;
     27 void add(int u, int v,double val){
     28     w[tot]  = val; to[tot] = v;
     29     nx[tot] = head[u]; head[u] = tot++;
     30     w[tot]  = 0; to[tot] = u;
     31     nx[tot] = head[v]; head[v] = tot++;
     32 }
     33 int bfs(int s, int t){
     34     queue<int> q;
     35     memset(deep, 0, sizeof(int)*(n+3));
     36     q.push(s);
     37     deep[s] = 1;
     38     while(!q.empty()){
     39         int u = q.front();
     40         q.pop();
     41         for(int i = head[u]; ~i; i = nx[i]){
     42             if(w[i] > 0 && deep[to[i]] == 0){
     43                 deep[to[i]] = deep[u] + 1;
     44                 q.push(to[i]);
     45             }
     46         }
     47     }
     48     if(deep[t] > 0) return 1;
     49     return 0;
     50 }
     51 double Dfs(int u, int t, double flow){
     52     if(u == t) return flow;
     53     for(int &i = cur[u]; ~i; i = nx[i]){
     54         if(deep[u] + 1 == deep[to[i]] && w[i] > 0){
     55             double di = Dfs(to[i], t, min(w[i], flow));
     56             if(di > 0){
     57                 w[i] -= di, w[i^1] += di;
     58                 return di;
     59             }
     60         }
     61     }
     62     return 0;
     63 }
     64 
     65 int Dinic(int s, int t){
     66     double ans = 0, tmp;
     67     while(bfs(s, t)){
     68         for(int i = 0; i <= n+1; i++) cur[i] = head[i];
     69         while(tmp = Dfs(s, t, INF)) ans += tmp;
     70     }
     71     return ans;
     72 }
     73 
     74 bool check(double x){
     75     memset(head, -1, sizeof(int) * (n+2));
     76     tot = 0;
     77     int s = 0, t = n + 1;
     78     for(int i = 1; i <= m; i++){
     79         add(u[i], v[i], 1);
     80         add(v[i], u[i], 1);
     81     }
     82     for(int i = 1; i <= n; i++){
     83         add(s, i, m);
     84         add(i, t, m+2*x-d[i]);
     85     }
     86     return (m*n-Dinic(s,t))/2.0 >= 1e-6;
     87 }
     88 
     89 void Find(int x){
     90     vis[x] = 1;
     91     for(int i = head[x]; ~i; i = nx[i])
     92         if(w[i] > 0 && !vis[to[i]])
     93             Find(to[i]);
     94 }
     95 
     96 int main(){
     97     while(~scanf("%d%d", &n, &m)){
     98         if(m == 0){
     99             printf("1
    1
    ");
    100             continue;
    101         }
    102         memset(d, 0, sizeof(int)*(n+1));
    103         for(int i = 1; i <= m; i++){
    104             scanf("%d%d", &u[i], &v[i]);
    105             d[u[i]]++; d[v[i]]++;
    106         }
    107         double l = 0, r = m,  mid;
    108         while(r - l >= 1.0/n/n){
    109             mid = (l+r)/2;
    110             if(check(mid)) l = mid;
    111             else r = mid;
    112         }
    113         check(l);
    114         memset(vis, 0, sizeof(vis));
    115         Find(0);
    116         int ans = 0;
    117         for(int i = 1; i <= n; i++) ans += vis[i];
    118         printf("%d
    ", ans);
    119         for(int i = 1; i <= n; i++)
    120             if(vis[i]) printf("%d
    ", i);
    121     }
    122     return 0;
    123 }
    View Code
  • 相关阅读:
    利用同步辅助类CountDownLatch计算多线程的运行时间
    i++的原子性问题
    Volatile关键字以及线程的内存可见性问题
    创建线程的第三种方式以及简单使用
    java8新特性-lambda表达式和stream API的简单使用
    springboot整合activemq
    springboot整合redis单机及集群
    JAVA-基础(一)
    CentOS-文件操作
    理解AngularJS的作用域Scope
  • 原文地址:https://www.cnblogs.com/MingSD/p/9524392.html
Copyright © 2011-2022 走看看