HUST 1027 Enemy Target!
求二分图的最小点覆盖集,并输出
对于每一个a[i][j]=1,我们从行i-->列j建立一条边
显然,这张图是一张二分图。左边的节点代表删除哪一行,右边的节点代表删除哪一列。中间的边代表所有a[i][j]为1的点。
现在,我们需要做的事情就是找出最少的点,使这些点覆盖住所有的边(即删去哪几行哪几列,没有士兵)
最少的点,使这些点覆盖住所有的边 这个东西是最小点覆盖集。
对于一张二分图来说,在数量上,最小点覆盖集=最大匹配
如果 最大匹配>坦克数量,那么输出无解
剩下的情况就是有解了,如何寻找解?这问题困扰了我很久......最后还是看了别人的博客。
此外,这题目点最多有2000个,为什么匈牙利算法可以AC......不是o(n^3)效率的吗......
详见北京大学神犇Matrix67的讲解http://blog.csdn.net/niushuai666/article/details/7036897
#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]; vector<int>Gl[MAXN]; vector<int>Gr[MAXN]; vector<int> ansr; vector<int> ansc; int flagl[MAXN], flagr[MAXN]; int flag[MAXN]; int mat[MAXN][MAXN]; 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; } void dfs(int now, int x) { if (x==0) { flagl[now] = 1; for (int i = 0; i<Gl[now].size(); i++) if (flagr[Gl[now][i]] == 0 && cx[now] == Gl[now][i]) dfs(Gl[now][i], 1); } else { flagr[now] = 1; for (int i = 0; i<Gr[now].size(); i++) if (flagl[Gr[now][i]] == 0 && cy[now] != Gr[now][i]) dfs(Gr[now][i], 0); } } 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++) Gl[i].clear(); for (int i = 0; i<=COLUMN; i++) Gr[i].clear(); for (int i = 0; i < ROW; i++) for (int j = 0; j < COLUMN; j++) if (s[i][j] == '1') { g[i][j] = 1; Gl[i].push_back(j); Gr[j].push_back(i); } nx = ROW; ny = COLUMN; int ans = MaxMatch(); if (ans>N) printf("NOT ENOUGH TANK\n"); else { printf("%d\n", ans); memset(flagl, 0, sizeof flagl); memset(flagr, 0, sizeof flagr); memset(flag, 0, sizeof flag); memset(mat, 0, sizeof mat); ansr.clear(); ansc.clear(); for (int i = 0; i<ROW; i++) if (cx[i] != -1) flag[cx[i]] = 1; for (int j = 0; j<COLUMN; j++) if (!flag[j]) dfs(j, 1); for (int i = 0; i<ROW; i++) if (flagl[i]) ansr.push_back(i); for (int i = 0; i<COLUMN; i++) if (!flagr[i]) ansc.push_back(i); printf("ROW:"); for (int i = 0; i < ansr.size(); i++) printf(" %d", ansr[i]+1); printf("\n"); printf("COLUMN:"); for (int i = 0; i < ansc.size(); i++) printf(" %d", ansc[i]+1); printf("\n"); } } return 0; }