模板汇总——网络流

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\n", 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\n",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\n", 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\n", 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\n1\n");
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\n", ans);
119         for(int i = 1; i <= n; i++)
120             if(vis[i]) printf("%d\n", i);
121     }
122     return 0;
123 }
View Code

 

posted @ 2018-08-23 16:08  Schenker  阅读(323)  评论(0编辑  收藏  举报