最小费用最大流算法 就好像是EK的变形。bfs的时候类似spfa找最短路,更新cost。
因为我是从 EK 的代码基础上改的,然后没发现if(u == end) break;和这个不一样。。。一直WA,注意数组开大一点。
先搜到的不一定是最优结果啊!!!
最小费用 最大流 邻接表模版。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <queue> 5 using namespace std; 6 #define INF 0x7fffffff 7 int low[1001],path[1001]; 8 struct node 9 { 10 int u,v,w,next,re,cost; 11 }edge[501*201]; 12 int first[1001],dis[1001],in[1001]; 13 int str,end,n,m,t; 14 char ch[501][501]; 15 struct point 16 { 17 int x,y; 18 }queh[1001],quem[1001]; 19 int Abs(int a) 20 { 21 return a >= 0?a:-a; 22 } 23 void CL() 24 { 25 t = 1; 26 memset(first,-1,sizeof(first)); 27 } 28 void add(int u,int v,int w,int cost) 29 { 30 edge[t].u = u; 31 edge[t].v = v; 32 edge[t].w = w; 33 edge[t].re = t+1; 34 edge[t].cost = cost; 35 edge[t].next = first[u]; 36 first[u] = t ++; 37 38 edge[t].u = v; 39 edge[t].v = u; 40 edge[t].w = 0; 41 edge[t].re = t-1; 42 edge[t].cost = -cost; 43 edge[t].next = first[v]; 44 first[v] = t ++; 45 } 46 int bfs() 47 { 48 int u,v,i; 49 memset(path,-1,sizeof(path)); 50 for(i = 0;i <= end;i ++) 51 { 52 dis[i] = INF; 53 in[i] = 0; 54 } 55 queue<int> que; 56 que.push(str); 57 in[str] = 1; 58 dis[str] = 0; 59 low[str] = INF; 60 while(!que.empty()) 61 { 62 u = que.front(); 63 in[u] = 0; 64 que.pop(); 65 for(i = first[u]; i != -1; i = edge[i].next) 66 { 67 v = edge[i].v; 68 if(edge[i].w&&dis[v] > dis[u] + edge[i].cost) 69 { 70 low[v] = low[u] < edge[i].w ? low[u]:edge[i].w; 71 path[v] = i; 72 dis[v] = dis[u] + edge[i].cost; 73 if(!in[v]) 74 { 75 que.push(v); 76 in[v] = 1; 77 } 78 } 79 } 80 } 81 if(path[end] == -1) 82 return -1; 83 else 84 return low[end]; 85 } 86 int mcmf() 87 { 88 int ans = 0,res,now,temp; 89 while((res = bfs()) != -1) 90 { 91 now = end; 92 while(now != str) 93 { 94 temp = path[now]; 95 edge[edge[temp].re].w += res; 96 edge[temp].w -= res; 97 ans += res*edge[temp].cost; 98 now = edge[temp].u; 99 } 100 } 101 return ans; 102 } 103 int build() 104 { 105 int i,j,numh = 1,numm = 1; 106 for(i = 0;i < n;i ++) 107 { 108 for(j = 0;j < m;j ++) 109 { 110 if(ch[i][j] == 'm') 111 { 112 quem[numm].x = i; 113 quem[numm].y = j; 114 numm ++; 115 } 116 else if(ch[i][j] == 'H') 117 { 118 queh[numh].x = i; 119 queh[numh].y = j; 120 numh ++; 121 } 122 } 123 } 124 numm --; 125 numh --; 126 for(i = 1;i <= numm;i ++) 127 { 128 for(j = 1;j <= numh;j ++) 129 { 130 int d; 131 d = Abs(quem[i].x-queh[j].x)+Abs(quem[i].y-queh[j].y); 132 add(i,numm+j,1,d); 133 } 134 } 135 for(i = 1;i <= numm;i ++) 136 { 137 add(0,i,1,0); 138 } 139 for(i = 1;i <= numm;i ++) 140 { 141 add(numm+i,2*numm+1,1,0); 142 } 143 return 2*numm; 144 } 145 int main() 146 { 147 int i; 148 while(scanf("%d%d",&n,&m)!=EOF) 149 { 150 if(n == 0&&m == 0) break; 151 CL(); 152 for(i = 0;i < n;i ++) 153 scanf("%s",ch[i]); 154 155 str = 0;end = build()+1; 156 printf("%d\n",mcmf()); 157 } 158 return 0; 159 }