SCL - MCMF based on Primal Dual
2017-03-19 16:35:01
最小费用流 之 原始对偶 (Primal-Dual) 算法
这个算法在搞竞赛时并没有学... 但是在申研时和通通问我的题目中都涉及到了,决定学习下、写一发。
学习推荐博客:https://artofproblemsolving.com/community/c1368h1020435
1 #include <stdio.h> 2 #include <string.h> 3 #include <deque> 4 #include <vector> 5 #include <algorithm> 6 using namespace std; 7 8 const int MAXN = 1010; 9 const int MAXM = 2010; 10 const int INF = 0x3F3F3F3F; 11 12 struct edge{ 13 int v,nxt,cost,cp; 14 edge() {} 15 edge(int a,int b,int c,int d) : v(a),nxt(b),cost(c),cp(d) {} 16 }; 17 18 struct MCMF_Primal_Dual{ 19 edge e[MAXM]; 20 int N; 21 int sou,sin,cost,piS; 22 int first[MAXN],ecnt; 23 int link[MAXN]; 24 bool vis[MAXN]; 25 26 void init(int n,int a,int b){ 27 N = n; 28 sou = a; 29 sin = b; 30 memset(first,-1,sizeof(first)); 31 ecnt = ecnt = cost = piS = 0; 32 } 33 void add_edge(int u,int v,int fee,int cap){ 34 e[ecnt] = edge(v,first[u],fee,cap); 35 first[u] = ecnt++; 36 e[ecnt] = edge(u,first[v],-fee,0); 37 first[v] = ecnt++; 38 } 39 int aug(int p,int minf){ 40 if(p == sin) return cost += piS * minf,minf; 41 vis[p] = true; 42 int tmp = minf; 43 for(int i = first[p]; ~i; i = e[i].nxt){ 44 if(e[i].cp && !e[i].cost && !vis[e[i].v]){ 45 int d = aug(e[i].v,tmp < e[i].cp ? tmp : e[i].cp); 46 e[i].cp -= d,e[i ^ 1].cp += d,tmp -= d; 47 if(!tmp) return minf; 48 } 49 } 50 return minf - tmp; 51 } 52 bool modlabel(){ 53 static int D[MAXN]; 54 memset(D,0x3f,sizeof(D)); 55 D[sin] = 0; 56 static deque<int> Q; 57 Q.push_back(sin); 58 while(Q.size()){ 59 int dt,now = Q.front(); Q.pop_front(); 60 for(int i = first[now]; ~i; i = e[i].nxt){ 61 if(e[i ^ 1].cp && (dt = D[now] - e[i].cost) < D[e[i].v]) 62 (D[e[i].v] = dt) <= D[Q.size() ? Q.front() : 0] ? 63 Q.push_front(e[i].v) : Q.push_back(e[i].v); 64 } 65 } 66 for(int i = 0; i <= N; ++i) 67 for(int j = first[i]; ~j; j = e[j].nxt) 68 e[j].cost += D[e[j].v] - D[i]; 69 piS += D[sou]; 70 return D[sou] < INF; 71 } 72 pair<int,int> solve(){ 73 int sum_flow = 0; 74 while(modlabel()){ 75 while(1){ 76 memset(vis,false,sizeof(vis)); 77 int f = aug(sou,INF); 78 if(!f) break; 79 sum_flow += f; 80 } 81 } 82 return make_pair(cost,sum_flow); 83 } 84 int Dfs(int p,int minf){ 85 if(p == sin || minf == 0) return minf; 86 vis[p] = true; 87 for(int i = first[p]; ~i; i = e[i].nxt){ 88 if(e[i ^ 1].cp && !vis[e[i].v]){ 89 int d = Dfs(e[i].v,min(minf,e[i ^ 1].cp)); 90 if(d > 0){ 91 e[i ^ 1].cp -= d; 92 link[p] = e[i].v; 93 // e[i].cp += d; 这句可加可不加,如果需要从残余网络复原,则加 94 return d; 95 } 96 } 97 } 98 return 0; 99 } 100 vector<vector<int> > find_path(){ 101 vector<vector<int> > res; 102 while(1){ 103 memset(vis,false,sizeof(vis)); 104 int flow = Dfs(sou,INF); 105 if(!flow) break; 106 vector<int> tmp(0); 107 int p = sou; 108 while(p != sin){ 109 tmp.push_back(p); 110 p = link[p]; 111 } 112 tmp.push_back(sin); 113 tmp.push_back(flow); 114 res.push_back(tmp); 115 } 116 return res; 117 } 118 }SSR; 119 120 int main(){ 121 int n = 5; 122 SSR.init(n,0,n); 123 SSR.add_edge(0,1,0,2); 124 SSR.add_edge(1,2,1,1); SSR.add_edge(2,5,1,1); 125 SSR.add_edge(1,3,1,1); SSR.add_edge(3,5,1,1); 126 SSR.add_edge(1,4,2,1); SSR.add_edge(4,5,2,1); 127 pair<int,int> res = SSR.solve(); 128 vector<vector<int> > res_path = SSR.find_path(); 129 for(int i = 0; i < res_path.size(); ++i){ 130 vector<int> &now = res_path[i]; 131 for(int j = 0; j < now.size(); ++j) printf("%d ",now[j]); 132 puts(""); 133 } 134 printf("%d %d\n",res.first,res.second); 135 return 0; 136 }

浙公网安备 33010602011771号