zoukankan      html  css  js  c++  java
  • 图论算法----网络流

    模板:

    最大流:

    普通增广:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 #define maxn 1010
     8 #define INF 0x3f3f3f3f
     9 using namespace std;
    10 struct edge{
    11     int to,cap,rev;
    12 };
    13 vector<edge>G[maxn];
    14 bool used[maxn];
    15 void addedge(int from,int to,int cap){
    16     G[from].push_back((edge){to,cap,G[to].size()});
    17     G[to].push_back((edge){from,0,G[from].size()-1});
    18 }
    19 int dfs(int v,int t,int f){
    20     if (v==t)return f;
    21     used[v]=true;
    22     for (int i=0;i<G[v].size();++i){
    23         edge &e = G[v][i];
    24         if(!used[e.to]&&e.cap>0){
    25             int d  = dfs(e.to,t,min(f,e.cap));
    26             if (d>0){
    27                 e.cap-=d;
    28                 G[e.to][e.rev].cap +=d;
    29                 return d;
    30             }
    31         }
    32     }
    33     return 0;
    34 }
    35 int max_flow(int s,int t){
    36     int flow = 0;
    37     while(1){
    38         memset(used,0,sizeof(used));
    39         int f = dfs(s,t,INF);
    40         if(f==0)return flow;
    41         flow+=f;
    42     }
    43 }
    44 int main (){
    45 
    46 
    47 }
    View Code

    Dinic:

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<math.h>
     5 #include<iostream>
     6 #include<string>
     7 #include<algorithm>
     8 #include<vector>
     9 #include<queue>
    10 #include<stack>
    11 #include<map>
    12 #define maxn 200001
    13 #define INF 0x3f3f3f3f
    14 using namespace std;
    15 struct edge{
    16     int to,cap,rev;
    17 };
    18 vector<edge>G[maxn];
    19 void addedge(int from,int to,int cap){
    20     G[from].push_back((edge){to,cap,G[to].size()});
    21     G[to].push_back((edge){from,0,G[from].size()-1});
    22 }
    23 int level[maxn];//点的深度
    24 int iter[maxn];//当前遍历到的边的下标
    25 void bfs(int s){
    26     memset(level,-1,sizeof(level));
    27     queue<int>q;
    28     level[s]=0;
    29     q.push(s);
    30     while(!q.empty()){
    31         int v = q.front();
    32         q.pop();
    33         for (int i=0;i<G[v].size();++i){
    34             edge &e = G[v][i];
    35             if (e.cap>0&&level[e.to]<0){
    36                 level[e.to]=level[v]+1;
    37                 q.push(e.to);
    38             }
    39         }
    40     }
    41 }
    42 int dfs(int v,int t,int f){
    43     if (v==t)return f;
    44     for (int &i =iter[v];i<G[v].size();++i){
    45         edge &e = G[v][i];
    46         if (e.cap>0&&level[v]<level[e.to]){
    47             int d = dfs(e.to,t,min(f,e.cap));
    48             if(d>0){
    49                 e.cap-=d;
    50                 G[e.to][e.rev].cap += d;
    51                 return d;
    52             }
    53         }
    54     }
    55     return 0;
    56 }
    57 int max_flow(int s,int t){
    58     int flow = 0;
    59     while(1){
    60         bfs(s);
    61         if(level[t]<0)return flow;
    62         memset(iter,0,sizeof(iter));
    63         int f ;
    64         while((f=dfs(s,t,INF))>0){
    65             flow+=f;
    66         }
    67     }
    68 }
    69 int N,M;
    70 int A[maxn],B[maxn];
    71 int a[maxn],b[maxn],w[maxn];
    72 void solve(){
    73     int s = N,t= s+1;
    74     for(int i=0;i<N;++i){
    75         addedge(i,t,A[i]);
    76         addedge(s,i,B[i]);
    77     }
    78     for(int i=0;i<M;++i){
    79         addedge(a[i]-1,b[i]-1,w[i]);
    80         addedge(b[i]-1,a[i]-1,w[i]);
    81     }
    82     int ans = max_flow(s,t);
    83     printf("%d
    ",ans);
    84 }
    85 int main (){
    86     while(scanf("%d%d",&N,&M)!=EOF){
    87         for(int i=0;i<N;++i)scanf("%d%d",&A[i],&B[i]);
    88         for(int i=0;i<M;++i)scanf("%d%d%d",&a[i],&b[i],&w[i]);
    89         solve();
    90     }
    91 }
    View Code

    SAP:

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<string.h>
      4 #include<math.h>
      5 #include<iostream>
      6 #include<string>
      7 #include<algorithm>
      8 #include<vector>
      9 #include<queue>
     10 #include<stack>
     11 #include<map>
     12 #define maxn 200001
     13 #define maxm 1800000
     14 #define INF 0x3f3f3f3f
     15 using namespace std;
     16 const int inf=(1<<29);
     17 struct EDGE{
     18     int v,next;
     19     int cap;
     20 }ee[maxm];
     21 int head[maxn],gap[maxn]; //dep[maxn];
     22 int n,m,src,des,siz;//src=start,des=end;
     23 void init(){
     24     siz=0;
     25     memset(head,-1,sizeof head);
     26 }
     27 void addedge(int u,int v,int cap){
     28     ee[siz].v=v,ee[siz].cap=cap;
     29     ee[siz].next=head[u];
     30     head[u]=siz++;
     31 
     32     ee[siz].v=u,ee[siz].cap=0;
     33     ee[siz].next=head[v];
     34     head[v]=siz++;
     35 }
     36 int dis[maxn],pre[maxn];
     37 int cur[maxn],aug[maxn];
     38 
     39 int SAP(int s, int e, int n)
     40 {
     41     int max_flow = 0, v, u = s;
     42     int id, mindis;
     43     aug[s] = inf;
     44     pre[s] = -1;
     45     memset(dis, 0, sizeof(dis));
     46     memset(gap, 0, sizeof(gap));
     47     gap[0] = n;
     48     for (int i = 0; i <= n; ++i){//初始化当前弧为第一条弧
     49         cur[i] = head[i];
     50     }
     51 
     52     while (dis[s] < n)
     53     {
     54         bool flag = false;
     55         if (u == e)
     56         {
     57             max_flow += aug[e];
     58             for (v = pre[e]; v != -1; v = pre[v])//路径回溯更新残留网络
     59             {
     60                 id = cur[v];
     61                 ee[id].cap -= aug[e];
     62                 ee[id^1].cap += aug[e];
     63                 aug[v] -= aug[e]; //修改可增广量,以后会用到
     64                 if (ee[id].cap == 0) u = v; //不回退到源点,仅回退到容量为0的弧的弧尾
     65             }
     66         }
     67         for (id = cur[u]; id != -1; id = ee[id].next)
     68         {   // 从当前弧开始查找允许弧
     69             v = ee[id].v;
     70             if (ee[id].cap > 0 && dis[u] == dis[v] + 1) //找到允许弧
     71             {
     72                 flag = true;
     73                 pre[v] = u;
     74                 cur[u] = id;
     75                 aug[v] = min(aug[u], ee[id].cap);
     76                 u = v;
     77                 break;
     78             }
     79         }
     80         if (flag == false)
     81         {
     82             if (--gap[dis[u]] == 0) break; /*gap优化层次树出现断层则结束算法*/
     83             mindis = n;
     84             cur[u] = head[u];
     85             for (id = head[u]; id != -1; id = ee[id].next)
     86             {
     87                 v = ee[id].v;
     88                 if (ee[id].cap > 0 && dis[v] < mindis)
     89                 {
     90                     mindis = dis[v];
     91                     cur[u] = id; //修改标号的同时修改当前弧
     92                 }
     93             }
     94             dis[u] = mindis + 1;
     95             gap[dis[u]]++;
     96             if (u != s) u = pre[u]; //回溯继续寻找允许弧
     97         }
     98     }
     99     return max_flow;
    100 }
    101 int N,M;
    102 int A[maxn],B[maxn];
    103 int a[maxn],b[maxn],w[maxn];
    104 void solve(){
    105     int s = N,t= s+1;
    106     for(int i=0;i<N;++i){
    107         addedge(i,t,A[i]);
    108         addedge(s,i,B[i]);
    109     }
    110     for(int i=0;i<M;++i){
    111         addedge(a[i]-1,b[i]-1,w[i]);
    112         addedge(b[i]-1,a[i]-1,w[i]);
    113     }
    114     int ans = SAP(s,t,t+1);
    115     printf("%d
    ",ans);
    116 }
    117 int main (){
    118     while(scanf("%d%d",&N,&M)!=EOF){
    119         init();
    120         for(int i=0;i<N;++i)scanf("%d%d",&A[i],&B[i]);
    121         for(int i=0;i<M;++i)scanf("%d%d%d",&a[i],&b[i],&w[i]);
    122         solve();
    123     }
    124 }
    View Code

     最小费用流:

    bellman-ford:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 #define maxn 1010
     8 #define maxm 1010
     9 #define INF 0x3f3f3f3f
    10 using namespace std;
    11 struct edge{int to,cap,cost,rev;};
    12 int V; //顶点数
    13 vector<edge> G[maxn];//邻接表
    14 int dist[maxn];//最短距离
    15 int prevv[maxn],preve[maxn];//最短路中前驱节点以及对应的边
    16 void addedge(int from ,int to, int cap, int cost){
    17     G[from].push_back((edge){to,cap,cost,G[to].size()});
    18     G[to].push_back((edge){from,0,-cost,G[from].size()-1});
    19 }
    20 
    21 //求从s到t的流量为f的最小费用流,
    22 //如果无法增广返回-1
    23 //复杂度:O(F|V||E|)
    24 int min_cost_flow(int s, int t,int f){
    25     int res = 0;
    26     while(f>0){
    27         //利用bellman-ford求解最短路
    28         fill (dist,dist+V,INF);
    29         dist[s]=0;
    30         bool update = true;
    31         while(update){
    32             update = false;
    33             for(int v = 0; v<V; v++){
    34                 if(dist[v]==INF)continue;
    35                 for (int i=0;i<G[v].size();++i){
    36                     edge &e =G[v][i];
    37                     if(e.cap>0&&dist[e.to]>dist[v]+e.cost){
    38                         dist[e.to]=dist[v]+e.cost;
    39                         prevv[e.to]=v;
    40                         preve[e.to]=i;
    41                         update = true;
    42                     }
    43                 }
    44             }
    45         }
    46         if (dist[t]==INF){
    47             //无法再增广
    48             return -1;
    49         }
    50 
    51         //沿着最短路尽量增广
    52          int d = f;
    53          for(int v = t; v!=s;v = prevv[v]){
    54             d = min(d,G[prevv[v]][preve[v]].cap);
    55          }
    56          f-=d;
    57          res+=d*dist[t];
    58          for(int v = t;v!=s;v = prevv[v]){
    59             edge &e = G[prevv[v]][preve[v]];
    60             e.cap -=d;
    61             G[v][e.rev].cap+=d;
    62          }
    63     }
    64     return res;
    65 }
    66 int main (){
    67     int n,m;
    68     while(scanf("%d%d",&n,&m)!=EOF){
    69         V=n+1;
    70         for(int i=0;i<m;++i){
    71             int a,b,c;
    72             scanf("%d%d%d",&a,&b,&c);
    73             addedge(a,b,1,c);
    74             addedge(b,a,1,c);
    75         }
    76         int ans = min_cost_flow(1,n,2);
    77         printf("%d
    ",ans);
    78     }
    79 }
    View Code

    Dijkstra:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 #define maxn 1010
     8 #define maxm 1010
     9 #define INF 0x3f3f3f3f
    10 using namespace std;
    11 typedef pair<int,int>P;//first 为最短距离,second为顶点编号
    12 struct edge{int to,cap,cost,rev; };
    13 int V; //顶点数
    14 vector<edge> G[maxn];//邻接表
    15 int dist[maxn];//最短距离
    16 int h[maxn];//顶点的势
    17 int prevv[maxn],preve[maxn];//最短路中前驱节点以及对应的边
    18 void addedge(int from ,int to, int cap, int cost){
    19     G[from].push_back((edge){to,cap,cost,G[to].size()});
    20     G[to].push_back((edge){from,0,-cost,G[from].size()-1});
    21 }
    22 
    23 //求从s到t的流量为f的最小费用流,
    24 //如果无法增广返回-1
    25 //复杂度:O(F|V||E|)
    26 int min_cost_flow(int s, int t,int f){
    27     int res = 0;
    28     fill(h,h+V,0);
    29     while(f>0){
    30         //利用Dijkstra更新h
    31         priority_queue<P, vector<P>,greater<P> >q;
    32         fill (dist,dist+V,INF);
    33         dist[s]=0;
    34         q.push(P(0,s));
    35         while(!q.empty()){
    36             P p = q.top();
    37             q.pop();
    38             int v = p.second;
    39             if (dist[v]<p.first)continue;
    40             for (int i=0;i<G[v].size();++i){
    41                 edge &e = G[v][i];
    42                 if (e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
    43                         dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
    44                         prevv[e.to]=v;
    45                         preve[e.to]=i;
    46                         q.push(P(dist[e.to],e.to));
    47                 }
    48             }
    49         }
    50         if (dist[t]==INF){
    51             //无法再增广
    52             return -1;
    53         }
    54         for (int v=0;v<V;++v){
    55             h[v]+=dist[v];
    56         }
    57 
    58         //沿着最短路尽量增广
    59          int d = f;
    60          for(int v = t; v!=s;v = prevv[v]){
    61             d = min(d,G[prevv[v]][preve[v]].cap);
    62          }
    63          f-=d;
    64          res+=d*h[t];
    65          for(int v = t;v!=s;v = prevv[v]){
    66             edge &e = G[prevv[v]][preve[v]];
    67             e.cap -=d;
    68             G[v][e.rev].cap+=d;
    69          }
    70     }
    71     return res;
    72 }
    73 
    74 int main (){
    75     int n,m;
    76     while(scanf("%d%d",&n,&m)!=EOF){
    77         V=n+1;
    78         for(int i=0;i<m;++i){
    79             int a,b,c;
    80             scanf("%d%d%d",&a,&b,&c);
    81             addedge(a,b,1,c);
    82             addedge(b,a,1,c);
    83         }
    84         int ans = min_cost_flow(1,n,2);
    85         printf("%d
    ",ans);
    86     }
    87 }
    View Code
  • 相关阅读:
    ubuntu后台运行命令
    jquery获取焦点位于的元素
    thymeleaf 处理模板为字符串
    以字符串形式获取excel单元格中的内容
    ajax 上传文件
    springboot logback
    javaService
    Assistant For Chess Cards
    E生活
    易兼职-找工作兼职平台
  • 原文地址:https://www.cnblogs.com/shuzy/p/3937614.html
Copyright © 2011-2022 走看看