图论算法----网络流

模板:

最大流:

普通增广:

 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\n",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\n",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\n",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\n",ans);
86     }
87 }
View Code

 

posted @ 2014-08-26 16:45  默默如潮  阅读(234)  评论(0编辑  收藏  举报