最大流增广路(KM算法) HDOJ 1533 Going Home

题目传送门

 1 /*
 2     最小费用流:KM算法是求最大流,只要w = -w就可以了,很经典的方法
 3 */
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <cstring>
 8 using namespace std;
 9
10 const int MAXN = 1e2 + 10;
11 const int INF = 0x3f3f3f3f;
12 int x[MAXN], y[MAXN];
13 int w[MAXN][MAXN];
14 int visx[MAXN], visy[MAXN];
15 int ly[MAXN];
16 int mx[MAXN], my[MAXN];
17 int hx[MAXN], hy[MAXN];
18 char maze[MAXN][MAXN];
19 int n, m, un, vn, d;
20
21 bool DFS(int u) {
22     visx[u] = true;
23     for (int i=1; i<=un; ++i)   {
24         if (!visy[i] && x[u] + y[i] == w[u][i]) {
25             visy[i] = true;
26             if (ly[i] == -1 || DFS (ly[i])) {
27                 ly[i] = u;  return true;
28             }
29         }
30         else if (x[u] + y[i] > w[u][i]) d = min (d, x[u] + y[i] - w[u][i]);
31     }
32     return false;
33 }
34
35 int KM(void)    {
36     for (int i=1; i<=un; ++i)   {
37         x[i] = -INF;
38         for (int j=1; j<=vn; ++j)   {
39             x[i] = max (x[i], w[i][j]);
40         }
41     }
42
43     memset (ly, -1, sizeof (ly));
44     memset (y, 0, sizeof (y));
45     for (int i=1; i<=un; ++i)    {
46         while (true)    {
47             memset (visx, false, sizeof (visx));
48             memset (visy, false, sizeof (visy));
49             d = INF;
50             if (DFS (i))    break;
51             for (int i=1; i<=un; ++i)   {
52                 if (visx[i])    x[i] -= d;
53             }
54             for (int j=1; j<=vn; ++j)   {
55                 if (visy[j])    y[j] += d;
56             }
57         }
58     }
59
60     int res = 0;
61     for (int i=1; i<=un; ++i)   {
62         res += x[i] + y[i];
63     }
64
65     return res;
66 }
67
68 int main(void)  {       //HDOJ 1533 Going Home
69     //freopen ("HDOJ_1533.in", "r", stdin);
70
71     while (scanf ("%d%d", &n, &m) == 2) {
72         if (!n && !m)   break;
73         for (int i=1; i<=n; ++i)    {
74             scanf ("%s", maze[i] + 1);
75         }
76         un = vn = 0;
77         for (int i=1; i<=n; ++i)    {
78             for (int j=1; j<=m; ++j)    {
79                 if (maze[i][j] == ‘m‘)  mx[++un] = i, my[un] = j;
80                 else if (maze[i][j] == ‘H‘) hx[++vn] = i, hy[vn] = j;
81             }
82         }
83         for (int i=1; i<=un; ++i)   {
84             for (int j=1; j<=vn; ++j)   {
85                 w[i][j] = -(abs (mx[i] - hx[j]) + abs (my[i] - hy[j]));
86             }
87         }
88         printf ("%d\n", -KM ());
89     }
90
91     return 0;
92 }
时间: 2024-10-16 22:59:06

最大流增广路(KM算法) HDOJ 1533 Going Home的相关文章

最大流增广路(KM算法) HDOJ 2255 奔小康赚大钱

题目传送门 1 /* 2 KM:裸题第一道,好像就是hungary的升级版,不好理解,写点注释 3 KM算法用来解决最大权匹配问题: 在一个二分图内,左顶点为X,右顶点为Y,现对于每组左右连接Xi,Yj有权w(i,j), 4 求一种匹配使得所有w(i,j)的和最大.也就是最大权匹配一定是完备匹配.如果两边的点数相等则是完美匹配. 5 如果点数不相等,其实可以虚拟一些点,使得点数相等,也成为了完美匹配.最大权匹配还可以用最大流去解决 6 */ 7 #include <cstdio> 8 #inc

最大流增广路(KM算法) HDOJ 1853 Cyclic Tour

题目传送门 1 /* 2 KM: 相比HDOJ_1533,多了重边的处理,还有完美匹配的判定方法 3 */ 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #include <cstring> 8 using namespace std; 9 10 const int MAXN = 1e2 + 10; 11 const int INF = 0x3f3f3f3f; 12 int x

网络最大流增广路模板(EK &amp; Dinic)

EK算法: int fir[maxn]; int u[maxm],v[maxm],cap[maxm],flow[maxm],nex[maxm]; int e_max; int p[maxn],q[maxn],d[maxn]; void add_edge(int _u,int _v,int _w) { int e; e=e_max++; u[e]=_u;v[e]=_v;cap[e]=_w; nex[e]=fir[u[e]];fir[u[e]]=e; e=e_max++; u[e]=_v;v[e]=

最大流——增广路算法

关于网络流的增广路算法,网上有很多详细介绍,这里是摘录的模板.详细请见:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html 1 #include<iostream> 2 #include<iomanip> 3 #include<ctime> 4 #include<climits> 5 #include<algorithm> 6 #include<queue>

网络最大流最短增广路Dinic算法模板

//1是源点,n是汇点. #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const int maxn=1000+10; const int INF=0x7FFFFFFF; struct E

hdu 3549 Flow Problem 增广路ford-fullkerson算法

#include<stdio.h> #include<string.h> #include<queue> #include<vector> #include<algorithm> using namespace std; const int N=1024*2; const int inf=1<<24; struct arc { int c,f; } g[N][N]; int n,m,i,j,u,v,c,f; int abs(int x

Power Network(最大流基础_增广路算法:多源多汇,自建总源点和总汇点)

 Power NetworkCrawling in process... Crawling failed Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description A power network consists of nodes (power stations, consumers and dispatchers) connected by p

Drainage Ditches(最大流基础_增广路算法)

 Drainage DitchesCrawling in process... Crawling failed Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover p

关于最短增广路算法和连续最短增广路算法的操作步骤

最短增广路算法(SAP): 1.初始化容量网络和网络流: 2.构造残留网络和层次网络,如果汇点不在层次网络中,则算法结束: 3.在层次网络中不断用BFS增广,直到层次网络中没有增广路为止:每次增广完毕,在层次网络中要去掉因改进流量而导致饱和的弧: 4.转到步骤(2). 连续最短增广路算法(Dinic): 1.初始化容量网络和网络流: 2.构造残留网络和层次网络,如果汇点不在层次网络中,则算法结束: 3.在层次网络中用一次DFS过程进行增广,DFS执行完毕,该阶段的增广也执行完毕: 4.转到步骤(