POJ 1719 Shooting Contest
题意:给定一个矩阵,每列有两个白点,其它都是黑点,如今要求每列选一个白点,使得每一行至少包括一个白点被选中
思路:二分图匹配,白点的位置行列建边,然后跑匹配,假设匹配数不等于行数,就是是无解,然后输出方案的时候注意,假设有位置是没匹配的,说明这个位置是多余的,可是还是要随意选一个白点来输出
代码:
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 1005; int t, r, c; vector<int> g[N]; int left[N], vis[N]; bool dfs(int u) { for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; if (vis[v]) continue; vis[v] = 1; if (!left[v] || dfs(left[v])) { left[v] = u; return true; } } return false; } int save[N]; void hungary() { int ans = 0; memset(left, 0, sizeof(left)); for (int i = 1; i <= r; i++) { memset(vis, 0, sizeof(vis)); if (dfs(i)) ans++; } if (ans != r) { printf("NO "); return; } for (int i = 1; i <= c; i++) printf("%d%c", left[i] ?left[i] : save[i], i == c ? ' ' : ' '); } int main() { scanf("%d", &t); while (t--) { scanf("%d%d", &r, &c); for (int i = 1; i <= r; i++) g[i].clear(); int tmp; for (int i = 1; i <= c; i++) { for (int j = 0; j < 2; j++) { scanf("%d", &tmp); save[i] = tmp; g[tmp].push_back(i); } } hungary(); } return 0; }