Poj--2195(最小费用最大流)
2014-12-22 21:10:56
思路:建立总源点,建边到各个男人,然后每个男人建有向边指向每栋房子,每栋房子建边到总汇点。当然每条边容量都为1。建完图就可以搞啦!
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 = 210; 21 22 int N,M,cntm,cnth,ed; 23 int mx[maxn],my[maxn]; 24 int hx[maxn],hy[maxn]; 25 int d[maxn][maxn]; 26 int dis[maxn],inq[maxn],pre[maxn]; 27 int first[maxn],edge[maxn],cost[maxn * maxn],cp[maxn * maxn],next[maxn * maxn],ver[maxn * maxn],ecnt; 28 char g[maxn][maxn]; 29 queue<int> Q; 30 31 void Spfa(){ 32 fill(dis,dis + maxn,INF); 33 memset(pre,0,sizeof(pre)); 34 memset(inq,0,sizeof(inq)); 35 while(!Q.empty()) Q.pop(); 36 Q.push(0); 37 inq[0] = 1; 38 dis[0] = 0; 39 while(!Q.empty()){ 40 int x = Q.front(); Q.pop(); 41 inq[x] = 0; 42 for(int i = first[x]; i != -1; i = next[i]){ 43 if(cp[i] == 0) continue; 44 int v = ver[i]; 45 if(dis[x] + cost[i] < dis[v]){ 46 dis[v] = dis[x] + cost[i]; 47 pre[v] = x; 48 edge[v] = i; 49 if(inq[v] == 0){ 50 inq[v] = 1; 51 Q.push(v); 52 } 53 } 54 } 55 } 56 } 57 58 int MCMF(){ 59 int min_cost = 0; 60 for(int tt = 1; tt <= cntm; ++tt){ 61 Spfa(); 62 for(int i = ed; i != 0; i = pre[i]){ 63 int id = edge[i]; 64 cp[id] -= 1; 65 cp[(id & 1) ? id + 1 : id - 1] += 1; 66 } 67 min_cost += dis[ed]; 68 } 69 return min_cost; 70 } 71 72 void Init(){ 73 memset(d,0,sizeof(d)); 74 memset(first,-1,sizeof(first)); 75 ecnt = 0; 76 } 77 78 void Add_edge(int u,int v){ 79 next[++ecnt] = first[u]; 80 ver[ecnt] = v; 81 cp[ecnt] = 1; 82 cost[ecnt] = d[u][v]; 83 first[u] = ecnt; 84 85 next[++ecnt] = first[v]; 86 ver[ecnt] = u; 87 cp[ecnt] = 0; 88 cost[ecnt] = -d[u][v]; 89 first[v] = ecnt; 90 } 91 92 int main(){ 93 while(scanf("%d%d",&N,&M) != EOF){ 94 if(N == 0 && M == 0) break; 95 Init(); 96 cntm = cnth = 0; 97 for(int i = 0; i < N; ++i) 98 scanf("%s",g[i]); 99 for(int i = 0; i < N; ++i){ 100 for(int j = 0; j < M; ++j){ 101 if(g[i][j] == 'H'){ 102 ++cnth; 103 hx[cnth] = i; 104 hy[cnth] = j; 105 } 106 else if(g[i][j] == 'm'){ 107 ++cntm; 108 mx[cntm] = i; 109 my[cntm] = j; 110 } 111 } 112 } 113 ed = cntm + cnth + 1; 114 for(int i = 1; i <= cntm; ++i) Add_edge(0,i); 115 for(int i = 1; i <= cnth; ++i) Add_edge(cntm + i,ed); 116 for(int i = 1; i <= cntm; ++i){ 117 for(int j = 1; j <= cnth; ++j){ 118 d[i][cntm + j] = abs(mx[i] - hx[j]) + abs(my[i] - hy[j]); 119 Add_edge(i,cntm + j); 120 } 121 } 122 printf("%d\n",MCMF()); 123 } 124 return 0; 125 }