You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

##POJ 3020 Antenna Placement

一、题目描述

*--代表城市o--代表空地

给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线。

公式:最小路径覆盖 = 总节点数-最大匹配数

我们要尽可能多的建立能覆盖两个城市的基站(二分匹配最大匹配),剩下的城市每个城市建立一个基站。

二、Code

#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;
}