费用流&网络流模版

费用流模版:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 using namespace std;
 5 
 6 const int Maxm=100000;//最大边数 
 7 const int Maxn=1000;//最大点数 
 8 struct Edge{
 9     Edge(){};
10     Edge(int a,int b,int c,int d,int e){
11         u=a;
12         v=b; 
13         f=c;
14         w=d;
15         nxt=e;
16     }
17     int u,v,f,w,nxt;//U当前点 V来自点 F最大流量 W费用 NXT下一个点 
18 };
19 int cnt=1;//边计数
20 int inf=2147483647;//无限大 
21 int g[Maxn+10];//点的边集的开始序号 
22 Edge e[Maxm+10];//边集 
23 int dist[Maxn+10];//费用 
24 int src,sink;//源点与汇点 
25 queue<int> que;//宽搜队列 
26 bool inque[Maxn+10];//宽搜判断标志 
27 int from[Maxn+10];//来源->用于计算费用 
28 int ans=0;//存储最小费用 
29 
30 inline int remin(int a,int b){
31     return a<b?a:b;
32 }
33 
34 inline void insert(int u,int v,int f,int w){
35     cnt++;
36     e[cnt]=Edge(u,v,f,w,g[u]);
37     g[u]=cnt;//增加一个边 
38 } 
39 
40 inline void addEdge(int u,int v,int f,int w){
41     insert(u,v,f,w);//插入正边 
42     insert(v,u,0,-w);//插入反边 
43 }
44 
45 inline bool spfa(){
46     while (!que.empty()) que.pop();//清空队列 
47     for (int i=0;i<=sink;i++) dist[i]=inf;//清最大值
48     que.push(src);
49     inque[src]=true;
50     dist[src]=0;//加入源点
51     //标准SPFA计算最短路 流量作为通行标准,费用作为路径长度 
52     while(!que.empty()){
53         int now=que.front();
54         que.pop();
55         for (int i=g[now];i;i=e[i].nxt){
56             if (e[i].f!=0 && dist[e[i].v]>dist[now]+e[i].w){
57                 dist[e[i].v]=dist[now]+e[i].w;
58                 from[e[i].v]=i;
59                 if (inque[e[i].v]==false){
60                     inque[e[i].v]=true;
61                     que.push(e[i].v);
62                 }
63             }
64         }
65         inque[now]=false;
66     } 
67     if (dist[sink]==inf) return false;//无法在增广 
68     return true;
69 }
70 
71 inline void calcAns(){
72     int minflow=inf;
73     for (int i=from[sink];i;i=from[e[i].u]) minflow=remin(minflow,e[i].f);//寻找整条路经的流量 
74     for (int i=from[sink];i;i=from[e[i].u]) {
75         e[i].f-=minflow;//正边减流量 
76         e[i^1].f+=minflow;//反边加流量 
77         ans+=e[i].w*minflow;//计算费用 
78     }
79 }
80 
81 inline void minCostFlow(){
82     while(spfa())calcAns();
83 }
84 
85 int main(){
86     minCostFlow();
87     return 0;
88 }

网络流模版:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<queue>
 4 using namespace std;
 5 
 6 const int Maxm=100000;//最大边数 
 7 const int Maxn=1000;//最大点数 
 8 struct Edge{
 9     Edge(){};
10     Edge(int a,int b,int c,int d,int e){
11         u=a;
12         v=b; 
13         f=c;
14         w=d;
15         nxt=e;
16     }
17     int u,v,f,w,nxt;//U当前点 V来自点 F最大流量 W费用 NXT下一个点 
18 };
19 int cnt=1;//边计数
20 int inf=2147483647;//无限大 
21 int g[Maxn+10];//点的边集的开始序号 
22 Edge e[Maxm+10];//边集 
23 int dist[Maxn+10];//费用 
24 int src,sink;//源点与汇点 
25 queue<int> que;//宽搜队列 
26 bool inque[Maxn+10];//宽搜判断标志 
27 int from[Maxn+10];//来源->用于计算费用 
28 int ans=0;//存储最小费用 
29 
30 inline int remin(int a,int b){
31     return a<b?a:b;
32 }
33 
34 inline void insert(int u,int v,int f,int w){
35     cnt++;
36     e[cnt]=Edge(u,v,f,w,g[u]);
37     g[u]=cnt;//增加一个边 
38 } 
39 
40 inline void addEdge(int u,int v,int f,int w){
41     insert(u,v,f,w);//插入正边 
42     insert(v,u,0,-w);//插入反边 
43 }
44 
45 inline bool spfa(){
46     while (!que.empty()) que.pop();//清空队列 
47     for (int i=0;i<=sink;i++) dist[i]=inf;//清最大值
48     que.push(src);
49     inque[src]=true;
50     dist[src]=0;//加入源点
51     //标准SPFA计算最短路 流量作为通行标准,费用作为路径长度 
52     while(!que.empty()){
53         int now=que.front();
54         que.pop();
55         for (int i=g[now];i;i=e[i].nxt){
56             if (e[i].f!=0 && dist[e[i].v]>dist[now]+e[i].w){
57                 dist[e[i].v]=dist[now]+e[i].w;
58                 from[e[i].v]=i;
59                 if (inque[e[i].v]==false){
60                     inque[e[i].v]=true;
61                     que.push(e[i].v);
62                 }
63             }
64         }
65         inque[now]=false;
66     } 
67     if (dist[sink]==inf) return false;//无法在增广 
68     return true;
69 }
70 
71 inline void calcAns(){
72     int minflow=inf;
73     for (int i=from[sink];i;i=from[e[i].u]) minflow=remin(minflow,e[i].f);//寻找整条路经的流量 
74     for (int i=from[sink];i;i=from[e[i].u]) {
75         e[i].f-=minflow;//正边减流量 
76         e[i^1].f+=minflow;//反边加流量 
77         ans+=e[i].w*minflow;//计算费用 
78     }
79 }
80 
81 inline void minCostFlow(){
82     while(spfa())calcAns();
83 }
84 
85 int main(){
86     minCostFlow();
87     return 0;
88 }
原文地址:https://www.cnblogs.com/WNJXYK/p/4063966.html