'commit'
This commit is contained in:
100
TangDou/AcWing/ErFenTu/POJ3020.md
Normal file
100
TangDou/AcWing/ErFenTu/POJ3020.md
Normal file
@@ -0,0 +1,100 @@
|
||||
##[$POJ$ $3020$ $Antenna$ $Placement$](http://poj.org/problem?id=3020)
|
||||
|
||||
### 一、题目描述
|
||||
*--代表城市,o--代表空地
|
||||
|
||||
给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线。
|
||||
|
||||
**公式:最小路径覆盖 = 总节点数-最大匹配数**
|
||||
|
||||
我们要尽可能多的建立能覆盖两个城市的基站(二分匹配最大匹配),剩下的城市每个城市建立一个基站。
|
||||
|
||||
|
||||
### 二、$Code$
|
||||
```cpp {.line-numbers}
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <cstdio>
|
||||
|
||||
using namespace std;
|
||||
const int N = 50, M = N * N;
|
||||
|
||||
char a[N][N]; // 原始矩阵
|
||||
|
||||
// 链式前向星
|
||||
int e[M], h[N], idx, w[M], ne[M];
|
||||
void add(int a, int b, int c = 0) {
|
||||
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
|
||||
}
|
||||
|
||||
int dx[] = {-1, 0, 1, 0}; // 上右下左
|
||||
int dy[] = {0, 1, 0, -1}; // 上右下左
|
||||
|
||||
int n, m; // n行m列
|
||||
|
||||
// 匈牙利算法
|
||||
int st[M], match[M];
|
||||
int dfs(int u) {
|
||||
for (int i = h[u]; ~i; i = ne[i]) {
|
||||
int v = e[i];
|
||||
if (st[v]) continue;
|
||||
st[v] = 1;
|
||||
if (match[v] == -1 || dfs(match[v])) {
|
||||
match[v] = u;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
#ifndef ONLINE_JUDGE
|
||||
freopen("POJ3020.in", "r", stdin);
|
||||
#endif
|
||||
int T;
|
||||
scanf("%d", &T);
|
||||
while (T--) {
|
||||
// 初始化链式前向星
|
||||
memset(h, -1, sizeof h);
|
||||
idx = 0;
|
||||
|
||||
scanf("%d %d", &n, &m); // n*m的矩阵
|
||||
|
||||
for (int i = 1; i <= n; i++) scanf("%s", a[i] + 1); // 使用char[],按行一次读入,快捷!
|
||||
|
||||
int cnt = 0; // 城市个数
|
||||
for (int i = 1; i <= n; i++) {
|
||||
for (int j = 1; j <= m; j++) {
|
||||
//*--代表城市,o--代表空地
|
||||
// 给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线网。
|
||||
if (a[i][j] == '*') {
|
||||
cnt++;
|
||||
// 四周探测
|
||||
for (int k = 0; k < 4; k++) {
|
||||
int tx = i + dx[k], ty = j + dy[k];
|
||||
if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
|
||||
// 城市到城市建边,无向图,尽量让无线网构建在两个城市上,这样才能省资源,要不一个城市一个无向网太费了
|
||||
if (a[tx][ty] == '*') add((i - 1) * m + j, (tx - 1) * m + ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 匈牙利
|
||||
memset(match, -1, sizeof match);
|
||||
int res = 0;
|
||||
for (int i = 1; i <= n * m; i++) {
|
||||
memset(st, 0, sizeof st);
|
||||
if (dfs(i)) res++;
|
||||
}
|
||||
// 无向图,重复计算,然后除以2,就是最大匹配数
|
||||
printf("%d\n", cnt - res / 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user