题目大意:给出一张表格,m行n列,每一列有两个白色的格子。现在要选出n个格子,使得每列恰好有一个格子,每行至少有一个格子。输出每一列选的格子在第几行。无解输出“NO”。(有SpecialJugde)
思路:二维的图,选点,很经典的二分图的模型。建完模之后,做最大匹配。这样首先要保证每一行要能被匹配到,如果max_match小于行数就输出NO。满足了每一行都有一个格子之后,要考虑每一列。现在每一列的状态是有格子和没格子。有格子的已经满足了,没有格子的只要任选一个格子就可以,因为不影响列上的情况(列要求至少有一个格子)。
CODE:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1010
using namespace std;
int cases;
int m,n;
bool map[MAX][MAX];
inline void Initialize();
bool Hungary(int x);
int main()
{
for(cin >> cases;cases; --cases) {
scanf("%d%d",&m,&n);
Initialize();
for(int x,y,i = 1;i <= n; ++i) {
scanf("%d%d",&x,&y);
map[x][i] = map[y][i] = true;
}
for(int i = 1;i <= m; ++i) {
memset(v,false,sizeof(v));
ans += Hungary(i);
}
if(ans < m) puts("NO");
else {
for(int i = 1;i <= n; ++i)
if(paired[i]) printf("%d ",paired[i]);
else
for(int j = 1;j <= m; ++j)
if(map[i][j]) {
printf("%d ",j);
break;
}
puts("");
}
}
return 0;
}
inline void Initialize()
{
memset(map,false,sizeof(map));
}
bool Hungary(int x)
{
for(int i = 1;i <= n; ++i)
if(map[x][i] && !v[i]) {
v[i] = true;
if(!paired[i] || Hungary(paired[i])) {
paired[i] = x;
return true;
}
}
return false;
}