hdu 3468 Treasure Hunting
二分图匹配
题意: 。。。 看了半天
我们可以从rally点出发到最近的rally点, 如果有treasure在这两个rally点的最短路径上, 我们可以拿走他。
思路也可以参见http://blog.csdn.net/wall_f/article/details/8990937
这种分析问题的思路太值得学习了。。
一开始没看懂题。。 在vj上找了个代码 (o(╯□╰)o。。 谴责一下自己。。)然后写了一下注释。。
写完注释发现就那么回事 不想再敲一遍了。。噗。。
1 /*Author :usedrose */ 2 /*Created Time :2015/8/3 21:00:00*/ 3 /*File Name :2.cpp*/ 4 #pragma comment(linker, "/STACK:1024000000,1024000000") 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <sstream> 9 #include <cstdlib> 10 #include <cstring> 11 #include <climits> 12 #include <vector> 13 #include <string> 14 #include <ctime> 15 #include <cmath> 16 #include <deque> 17 #include <queue> 18 #include <stack> 19 #include <set> 20 #include <map> 21 #define INF 0x3f3f3f3f 22 #define eps 1e-8 23 #define pi acos(-1.0) 24 #define MAXN 1110 25 #define MAXM 100110 26 #define OK cout << "ok" << endl; 27 #define o(a) cout << #a << " = " << a << endl 28 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 29 using namespace std; 30 typedef long long LL; 31 32 int vv[MAXM], nxt[MAXM], h[MAXN*MAXN], e; 33 char str[MAXN][MAXN]; 34 int n, m; 35 int dis[55][MAXN*MAXN]; 36 int d[MAXN][MAXN]; 37 int bx[MAXN], by[MAXN]; 38 39 void addedge(int u,int v) 40 { 41 vv[e] = v; 42 nxt[e] = h[u]; 43 h[u] = e++; 44 } 45 46 int vis[MAXN*MAXN], pre[MAXN*MAXN]; 47 int dx[] = {0, 0, 1, -1}; 48 int dy[] = {1, -1, 0, 0}; 49 50 int getid(char x) 51 { 52 if (isupper(x)) return x - 'A'; 53 if (islower(x)) return x - 'a' + 26; 54 if (x == '*') return -1; 55 return -2; 56 } 57 58 int getid(int x, int y) 59 { 60 return x*m + y; 61 } 62 63 bool inside(int x, int y) 64 { 65 return x >= 0 && x < n && y >= 0 && y < m; 66 } 67 68 69 void bfs(int x, int y) 70 { 71 queue<int> q; 72 memset(d, -1, sizeof(d)); 73 q.push(x), q.push(y); 74 d[x][y] = 0; 75 while (!q.empty()) { 76 x = q.front(); q.pop(); 77 y = q.front(); q.pop(); 78 for (int i = 0;i < 4; ++ i) { 79 int x1 = x + dx[i]; 80 int y1 = y + dy[i]; 81 if (inside(x1, y1) && str[x1][y1] != '#' && d[x1][y1] < 0) { 82 d[x1][y1] = d[x][y] + 1; 83 q.push(x1); q.push(y1); 84 } 85 } 86 } 87 } 88 89 bool init() 90 { 91 memset(bx, -1, sizeof(bx)); 92 for (int i = 0;i < n; ++ i) 93 for (int j = 0;j < m;++ j) { 94 int x = getid(str[i][j]); 95 if (x >= 0) { // if it is a rally point 96 bx[x] = i, by[x] = j; //note its position 97 bfs(i, j); // get the shortest path around it 98 for (int k = 0;k < n; ++ k) 99 for (int l = 0;l < m; ++ l) { 100 dis[x][k*m+l] = d[k][l]; // get the distances from the point to all nodes 101 if (getid(str[k][l]) >= 0 && d[k][l] == -1) return false;// if unreachable 102 } 103 } 104 } 105 for (int i = 0;i < n; ++ i) 106 for (int j = 0;j < m; ++ j) if (str[i][j] == '*') { // for all treasure 107 for (int k = 1;bx[k] != -1; ++ k) {// for all rally points 108 if (dis[k-1][i*m+j] + dis[k][i*m+j] == dis[k-1][getid(bx[k],by[k])]) // if treasure on the shortest path between two rallys 109 if (dis[k-1][i*m+j] != -1 && dis[k][i*m+j] != -1) 110 addedge(k, i*m+j); //we should add an edge 111 } 112 } 113 return true; 114 } 115 116 int dfs(int u) 117 { 118 for (int i = h[u]; i + 1;i = nxt[i]) { 119 int v = vv[i]; 120 if (vis[v]) continue; 121 vis[v] = 1; 122 if (pre[v] == -1 || dfs(pre[v])) { 123 pre[v] = u; 124 return 1; 125 } 126 } 127 return 0; 128 } 129 130 int solve() 131 { 132 if (!init()) return -1; 133 int ans = 0; 134 memset(pre, -1, sizeof(pre)); 135 for (int i = 1; bx[i] != -1;++ i) { 136 memset(vis, 0 ,sizeof(vis)); 137 ans += dfs(i); 138 } 139 return ans; 140 } 141 142 int main() 143 { 144 while (cin >> n >> m) { 145 memset(h, -1, sizeof(h)); 146 e = 0; 147 for (int i = 0;i < n; ++ i) 148 cin >> str[i]; 149 cout << solve() << endl; 150 } 151 return 0; 152 }