Poj--2135(最小费用最大流)
2014-12-21 23:00:54
思路:最小费用最大流启蒙题。
巫大叔的书里写了最小费用,把它和最大流分了开来。。。然后看了别人博客,就是在求增广路的时候求最短增广路,套上spfa。
这题其实就是从1到n求两边最短增广路就行了,几个注意点:
(1)无向边!所以要双向建边(由于还要间负费用反向边,所以其实是对于一条无向边要建4条有向边)
(2)最短增广路只用求两次(因为来回)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const int INF = 1 << 30; 20 const int maxn = 1010; 21 const int Maxn = 10010; 22 23 int first[maxn],next[Maxn << 2],ver[Maxn << 2],cost[Maxn << 2],cp[Maxn << 2],ecnt; 24 int N,M,pre[maxn],edge[maxn],inq[maxn],dis[maxn]; 25 queue<int> Q; 26 27 void Init(){ 28 memset(first,-1,sizeof(first)); 29 ecnt = 0; 30 } 31 32 void Add_edge(int u,int v,int fee){ 33 next[++ecnt] = first[u]; 34 ver[ecnt] = v; 35 cost[ecnt] = fee; 36 cp[ecnt] = 1; 37 first[u] = ecnt; 38 39 next[++ecnt] = first[v]; 40 ver[ecnt] = u; 41 cost[ecnt] = -fee; 42 cp[ecnt] = 0; 43 first[v] = ecnt; 44 } 45 46 void Spfa(){ 47 fill(dis,dis + maxn,INF); 48 memset(pre,0,sizeof(pre)); 49 memset(inq,0,sizeof(inq)); 50 while(!Q.empty()) Q.pop(); 51 Q.push(1); 52 inq[1] = 1; 53 dis[1] = 0; 54 while(!Q.empty()){ 55 int x = Q.front(); Q.pop(); 56 inq[x] = 0; 57 for(int i = first[x]; i != -1; i = next[i]){ 58 int v = ver[i]; 59 if(cp[i] == 0) continue; 60 if(dis[x] + cost[i] < dis[v]){ 61 dis[v] = dis[x] + cost[i]; 62 pre[v] = x; 63 edge[v] = i; 64 if(inq[v] == 0){ 65 inq[v] = 1; 66 Q.push(v); 67 } 68 } 69 } 70 } 71 } 72 73 int MCMF(){ 74 int min_cost = 0; 75 for(int t = 1; t <= 2; ++t){ 76 Spfa(); 77 for(int i = N; i != 1; i = pre[i]){ 78 int id = edge[i]; 79 cp[id] -= 1; 80 cp[(id & 1) ? id + 1 : id - 1] += 1; 81 } 82 min_cost += dis[N]; 83 } 84 return min_cost; 85 } 86 87 int main(){ 88 int a,b,c; 89 Init(); 90 scanf("%d%d",&N,&M); 91 for(int i = 1; i <= M; ++i){ 92 scanf("%d%d%d",&a,&b,&c); 93 Add_edge(a,b,c); 94 Add_edge(b,a,c); 95 } 96 printf("%d\n",MCMF()); 97 return 0; 98 }