HDU 1498 50 years,50 colors
题意
n*n的矩形中放入颜色值为[1,50]的气球,要求每一个人扎k次,每扎一次,可将同行或者同列相同颜色的气球全部扎破。求是否存在不可能全部扎破的气球,按照升序规律输出气球的颜色。
思路
每种颜色进行最小点覆盖运算,如果最小覆盖点num>k,则该颜色气球不能全部扎破。 矩形行列分别为集合A和集合B,如果判断颜色k气球,则如果map [i] [j] = k,则表示存在一条边,这样便可以转换成最小点覆盖问题,只需要找出最小的点,清除掉两集合之间所有的边即。
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std
;
const int N
= 105;
int map
[N
][N
];
int link
[N
];
int useif
[N
];
int ans
[N
];
int len
;
int n
, k
;
int dfs(int t
, int col
)
{
for(int i
= 0; i
< n
; i
++)
{
if(!useif
[i
] && map
[t
][i
] == col
)
{
useif
[i
] = 1;
if(link
[i
] == -1 || dfs(link
[i
], col
))
{
link
[i
] = t
;
return 1;
}
}
}
return 0;
}
int maxMatch(int col
)
{
memset(link
, -1, sizeof(link
));
int num
= 0;
for(int i
= 0; i
< n
; i
++)
{
memset(useif
, 0, sizeof(useif
));
if(dfs(i
, col
)) num
++;
}
return num
;
}
int main()
{
while(scanf("%d %d", &n
, &k
) && n
&& k
)
{
memset(map
, 0, sizeof(map
));
len
= 0;
for(int i
= 0; i
< n
; i
++)
for(int j
=0;j
<n
;j
++)
scanf("%d", &map
[i
][j
]);
for(int i
= 1; i
<= 50; i
++)
{
if(maxMatch(i
) > k
)
ans
[len
++] = i
;
}
if(!len
)
printf("-1\n");
else
{
for(int i
=0;i
<len
-1;i
++)
printf("%d ", ans
[i
]);
printf("%d\n",ans
[len
- 1]);
}
}
return 0;
}