版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mobius_strip/article/details/88603881
题目
有一个棋盘格,里面有的方格中有石头,可以在某行或某列开炮将对应行或列的石头消除。为最少的开炮次数和策略。
分析
图论,König定理。
说明
好久没刷题了。。。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int maps[1001][1001];
int new_map[2002][2002];
int used[2002], linkl[2002];
int visit[2002], linkr[2002];
int dfs(int s, int n)
{
visit[s] = 1;
for (int i = 1 ; i <= n; ++ i) {
if (new_map[s][i] && !used[i]) {
used[i] = 1;
if (linkl[i] == -1 || dfs(linkl[i], n)) {
linkl[i] = s;
linkr[s] = i;
return 1;
}
}
}
return 0;
}
int main()
{
int R, C, N, r, c;
while (~scanf("%d%d%d", &R, &C, &N) && N) {
int M = R + C;
for (int i = 1; i <= M; ++ i) {
for (int j = 1; j <= M; ++ j) {
new_map[i][j] = 0;
}
}
for (int i = 1; i <= N; ++ i) {
scanf("%d%d", &r, &c);
new_map[r][R+c] = 1;
new_map[R+c][r] = 1;
}
for (int i = 1; i <= M; ++ i) {
linkl[i] = -1;
linkr[i] = -1;
}
int sum = 0;
for(int i = 1 ; i <= M; ++ i) {
for (int j = 1; j <= M; ++ j) {
used[j] = 0;
visit[j] = 0;
}
sum += dfs(i, M);
}
for (int i = 1; i <= M; ++ i) {
used[i] = 0;
visit[i] = 0;
}
for (int i = 1; i <= M; ++ i) {
if (linkr[i] == -1) {
dfs(i, M);
}
}
printf("%d", sum/2);
for (int i = 1; i <= R; ++ i) {
if (!visit[i]) {
printf(" r%d", i);
}
}
for (int i = R+1; i <= M; ++ i) {
if (used[i]) {
printf(" c%d", i-R);
}
}
puts("");
}
return 0;
}