SCL--最小费用最大流
2015-09-04 22:42:49
总结:由于以前的代码风格不同,所以现在有必要总(zhan)结(tie)一个最新的MCMF模板了。
用SPFA实现的,必要时可以上优化过的Dijstra。
1 struct edge{ 2 int v,next,cost,cp; 3 }; 4 5 struct MCMF{ 6 edge e[MAXM]; 7 int sou,sin; 8 int first[MAXN],ecnt; 9 int dis[MAXN]; 10 int prev[MAXN],pree[MAXN],inq[MAXN]; 11 void init(int a,int b){ 12 sou = a; 13 sin = b; 14 memset(first,-1,sizeof(first)); 15 ecnt = 0; 16 } 17 void add_edge(int u,int v,int cap,int fee){ 18 e[ecnt].next = first[u]; 19 e[ecnt].v = v; 20 e[ecnt].cp = cap; 21 e[ecnt].cost = fee; 22 first[u] = ecnt++; 23 24 e[ecnt].next = first[v]; 25 e[ecnt].v = u; 26 e[ecnt].cp = 0; 27 e[ecnt].cost = -fee; 28 first[v] = ecnt++; 29 } 30 bool Spfa(){ 31 fill(dis,dis + MAXN,INF); 32 dis[sou] = 0; 33 MEM(prev,-1),MEM(inq,0); 34 queue<int> Q; 35 Q.push(sou); 36 while(!Q.empty()){ 37 int x = Q.front(); Q.pop(); 38 inq[x] = 0; 39 for(int i = first[x]; ~i; i = e[i].next){ 40 if(e[i].cp <= 0) continue; 41 int v = e[i].v; 42 if(dis[x] + e[i].cost < dis[v]){ 43 dis[v] = dis[x] + e[i].cost; 44 prev[v] = x; 45 pree[v] = i; 46 if(inq[v] == 0){ 47 inq[v] = 1; 48 Q.push(v); 49 } 50 } 51 } 52 } 53 return prev[sin] != -1; 54 } 55 int Solve(){ 56 //int sumf = 0; 57 int min_cost = 0; 58 while(Spfa()){ 59 int minf = INF; 60 for(int i = sin; i != sou; i = prev[i]){ 61 int id = pree[i]; 62 minf = min(minf,e[id].cp); 63 } 64 for(int i = sin; i != sou; i = prev[i]){ 65 int id = pree[i]; 66 e[id].cp -= minf; 67 e[id ^ 1].cp += minf; 68 } 69 //sumf += minf; 70 min_cost += dis[sin] * minf; 71 } 72 //printf("flow : %d\n",sumf); 73 return min_cost; 74 } 75 }MC;