HUST 1027 Enemy Target!
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HUST 1027 Enemy Target!相关的知识,希望对你有一定的参考价值。
求二分图的最小点覆盖集,并输出
对于每一个a[i][j]=1,我们从行i-->列j建立一条边
显然,这张图是一张二分图。左边的节点代表删除哪一行,右边的节点代表删除哪一列。中间的边代表所有a[i][j]为1的点。
现在,我们需要做的事情就是找出最少的点,使这些点覆盖住所有的边(即删去哪几行哪几列,没有士兵)
最少的点,使这些点覆盖住所有的边 这个东西是最小点覆盖集。
对于一张二分图来说,在数量上,最小点覆盖集=最大匹配
如果 最大匹配>坦克数量,那么输出无解
剩下的情况就是有解了,如何寻找解?这问题困扰了我很久......最后还是看了别人的博客。
此外,这题目点最多有2000个,为什么匈牙利算法可以AC......不是o(n^3)效率的吗......
得到匹配结果之后,构造最小点覆盖集的方法:
对于一条边i-j,若不选i就是选j,是吧?做完最大匹配后,我们查没一条边,若link[j]==-1,表明j没有选,那么我们就选i,选完row后,再来看列的,对于一条边i-j,若i选了,就不选j,若i没有选,就选j。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int MAXN = 1000 + 10; int nx, ny; int g[MAXN][MAXN]; int cx[MAXN], cy[MAXN]; int mk[MAXN]; int ROW, COLUMN, N; char s[MAXN][MAXN]; int flagr[MAXN]; int flagc[MAXN]; vector<int> ansr; vector<int> ansc; int path(int u) { for (int v = 0; v<ny; v++) { if (g[u][v] && !mk[v]) { mk[v] = 1; if (cy[v] == -1 || path(cy[v])) { cx[u] = v; cy[v] = u; return 1; } } } return 0; } int MaxMatch() { int res = 0; memset(cx, -1, sizeof(cx)); memset(cy, -1, sizeof(cy)); for (int i = 0; i<nx; i++) { if (cx[i] == -1) { memset(mk, 0, sizeof(mk)); res = res + path(i); } } return res; } int main() { while (~scanf("%d%d%d", &ROW, &COLUMN, &N)) { for (int i = 0; i < ROW; i++) scanf("%s", s[i]); memset(g, 0, sizeof g); for (int i = 0; i < ROW; i++) for (int j = 0; j < COLUMN; j++) if (s[i][j] == ‘1‘) g[i][j] = 1; nx = ROW; ny = COLUMN; int ans = MaxMatch(); if (ans>N) printf("NOT ENOUGH TANK\n"); else { printf("%d\n", ans); memset(flagr, 0, sizeof flagr); memset(flagc, 0, sizeof flagc); for (int i = 0; i < ROW; i++) { for (int j = 0; j < COLUMN; j++) { if (g[i][j]) { if (cy[j] == -1) { flagr[i] = 1; } } } } for (int i = 0; i < ROW; i++) { for (int j = 0; j < COLUMN; j++) { if (g[i][j]) { if (flagr[i] == 1){} else flagc[j] = 1; } } } for (int i = 0; i < nx; i++) if (flagr[i]) ansr.push_back(i + 1); for (int i = 0; i < ny; i++) if (flagc[i]) ansc.push_back(i + 1); printf("ROW:"); for (int i = 0; i < ansr.size(); i++) printf(" %d", ansr[i]); printf("\n"); printf("COLUMN:"); for (int i = 0; i < ansc.size(); i++) printf(" %d", ansc[i]); printf("\n"); } } return 0; }
以上是关于HUST 1027 Enemy Target!的主要内容,如果未能解决你的问题,请参考以下文章