UVa 11419 - SAM I AM

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/mobius_strip/article/details/88603881