题目大意:有一个r * c的矩形,每列有两个格子是白色的,其他的格子都是黑色的。
你有一把枪,枪里面有c发子弹,现在要求你一列一列的打中两个白色中的其中一个格子,使得所有c发子弹打完后,每一行的白色格子至少有一个被打中
解题思路:
将列归为一个点集,行归为另一个点集进行匹配
写法1:将列标记为1 – c,行标记为1+c – c + r,这样就可以进行匹配了,但这样的复杂度比较大。。。
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N = 2010;
vector<int> block[N];
int link[N];
int vis[N];
int r, c, e;
bool dfs(int u) {
for(int i = 0; i < block[u].size(); i++) {
if(!vis[block[u][i]]) {
vis[block[u][i]] = 1;
if(link[block[u][i]] == -1 || dfs(link[block[u][i]])) {
link[block[u][i]] = u;
return true;
}
}
}
return false;
}
int main() {
int test;
scanf("%d", &test);
while(test--) {
scanf("%d%d", &r, &c);
int x, y;
for(int i = 1; i <= c + r; i++)
block[i].clear();
for(int i = 1; i <= c; i++) {
scanf("%d%d", &x, &y);
block[i].push_back(c + x);
block[i].push_back(c + y);
block[c + x].push_back(i);
block[c + y].push_back(i);
}
memset(link, -1, sizeof(link));
int ans = 0;
for(int i = 1; i <= c; i++) {
memset(vis, 0 ,sizeof(vis));
if(dfs(i))
ans++;
}
if(ans == r) {
for(int i = 1; i <= c; i++) {
if(i != 1)
printf(" ");
int j;
for(j = 0; j < 2; j++)
if(link[block[i][j]] == i) {
printf("%d", block[i][j] - c);
break;
}
if(j == 2)
printf("%d", block[i][0] - c);
}
printf("\n");
}
else
printf("NO\n");
}
return 0;
}
写法2:
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1010;
vector<int> row[N];
int col[N][2];
int vis[N], link[N], r, c;
bool dfs(int u) {
for(int i = 0; i < row[u].size(); i++) {
if(vis[row[u][i]])
continue;
vis[row[u][i]] = 1;
if(!link[row[u][i]] || dfs(link[row[u][i]])) {
link[row[u][i]] = u;
return true;
}
}
return false;
}
void hungary() {
int ans = 0;
for(int i = 1; i <= r; i++) {
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
if(ans == r) {
for(int i = 1; i <= c; i++)
printf("%d%c", link[i] ? link[i]:col[i][0], i == c ? '\n': ' ');
}
else
printf("NO\n");
}
void init() {
scanf("%d%d", &r, &c);
int t;
for(int i = 1; i <= r; i++)
row[i].clear();
for(int i = 1; i <= c; i++)
for(int j = 0; j < 2; j++) {
scanf("%d", &t);
col[i][j] = t;
row[t].push_back(i);
}
memset(link, 0, sizeof(link));
}
int main() {
int test;
scanf("%d", &test);
while(test--) {
init();
hungary();
}
return 0;
}