poj 3320 Jessica's Reading Problem

来源:互联网 发布:淘宝自动上架软件 编辑:程序博客网 时间:2024/05/19 16:50

就是给一个h*w的矩阵,然后矩阵上有些地方有点,其他地方没有,现在要一些天线来覆盖他们

一个天线能覆盖两个相邻(上下左右相邻)的点(当然,如果一个点没有和它相邻的,那也需要用一个天线来覆盖)

然后问最少需要多少天线来覆盖所有点

二分图的最小边覆盖

无向图的最小边覆盖就是选取最少数量的边,使得图中的每个点都是所选边里的至少一条边的端点

二分图最小边覆盖就是顶点数(只取某一部的)-最大匹配数/2

具体的建图方式就是对于矩阵中每个有点的地方,都要在二分图中拆成两个点,左边一个右边一个

然后对于两个点相邻,假如说x和y相邻,那么就左x和右y连边,左y和右x连边,然后跑最大匹配,然后就出结果了

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <string>#include <fstream>#include <list>#include <stack>#include <queue>#include <deque>#include <algorithm>#include <map>#include <set>#include <vector>#define maxn 405#define maxm 405using namespace std;const int dx[4] = { 0, 0, -1, 1 };const int dy[4] = { 1, -1, 0, 0 };bool graph[maxn][maxm];bool vis[maxm];int match[maxn];int h, w;int N;char grid[42][12];int idx[42][12];bool used[42][12];bool find(int x){for (int j = 0; j < N; j++){if (graph[x][j] == true && vis[j] == false){vis[j] = true;if (match[j] == -1 || find(match[j])){match[j] = x;return true;}}}return false;}int main(){//freopen("input.txt", "r", stdin);int T;scanf("%d", &T);while (T--){int x, y;int sum = 0;scanf("%d%d", &h, &w);memset(graph, 0, sizeof(graph));memset(match, -1, sizeof(match));memset(idx, 0, sizeof(int) * 42 * 12);memset(used, 0, sizeof(used));for (int i = 0; i < h; i++){scanf("%s", grid[i]);}N = 0;for (int i = 0; i < h; ++i){for (int j = 0; j < w; ++j){if (grid[i][j] == '*')idx[i][j] = N++;}}//printf("N %d\n", N);for (int i = 0; i < h; ++i){for (int j = 0; j < w; ++j){if (grid[i][j] == '*'){used[i][j] = true;for (int k = 0; k < 4; ++k){x = i + dx[k]; y = j + dy[k];if (x >= 0 && x < h&&y >= 0 && y < w&&grid[x][y] == '*'&&!used[x][y]){graph[idx[i][j]][idx[x][y]] = true;graph[idx[x][y]][idx[i][j]] = true;}}}}}for (int i = 0; i < N; i++){memset(vis, 0, sizeof(vis));if (find(i)) sum += 1;}//printf("%d\n", sum);int ans = N - sum / 2;printf("%d\n", ans);}//while (1);return 0;}

0 0
原创粉丝点击