矩阵游戏 【二分图】

题目描述

小QQ是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个N \times NN×N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:

行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)

列交换操作:选择矩阵的任意两列,交换这两列(即交换对应格子的颜色)

游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。

对于某些关卡,小QQ百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!于是小QQ决定写一个程序来判断这些关卡是否有解。

输入输出格式

输入格式:

第一行包含一个整数TT,表示数据的组数。

接下来包含TT组数据,每组数据第一行为一个整数NN,表示方阵的大小;接下来NN行为一个N \times NN×N的0101矩阵(00表示白色,11表示黑色)。

输出格式:

包含TT行。对于每一组数据,如果该关卡有解,输出一行YesYes;否则输出一行NoNo。

输入输出样例

输入样例#1: 复制

2
2
0 0
0 1
3
0 0 1
0 1 0
1 0 0

输出样例#1: 复制

No
Yes

说明

对于20\%20%的数据,N ≤ 7N≤7

对于50\%50%的数据,N ≤ 50N≤50

对于100\%100%的数据,N ≤ 200N≤200

我的算法:dfs 太复杂

#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<sstream>
#include<string.h>
#include<cstring>
using namespace std;
bool vistr[210],vistc[210];
int d[210][210];
bool res,isstop;
int kcase,n;
void dfs(int level) {
	if(isstop) return;
	if(level==0) {
		res=true;
		isstop=true;
	} else {
		for(int i=0; i<n; i++) {
			if(vistr[i]) continue;
			for(int j=0; j<n; j++) {
				if(vistc[j]) continue;
				if(d[i][j]) {
					vistr[i]=true;
					vistc[j]=true;
					dfs(level-1);
					vistr[i]=false;
					vistc[j]=false;
				}

			}
		}

	}
}
int main() {

	cin>>kcase;
	while((kcase--)>0) {
		cin>>n;
		memset(vistr,0,sizeof(vistr));
		memset(vistc,0,sizeof(vistc));
		for(int i=0; i<n; i++) {
			for(int j=0; j<n; j++)
				cin>>d[i][j];
		}
		res=false;
		isstop=false;
		dfs(n);
		if(res)
			cout<<"Yes"<<endl;
		else
			cout<<"No"<<endl;

	}
}


二分图法

#include <cstdio>
#include <cstring>
const int maxn = 201;
int n, mark[maxn];
bool vis[maxn][maxn], y[maxn];
bool find(int x)
{
    for(int i = 1; i <= n; ++i)
        if(vis[x][i] && !y[i])
        {
            y[i] = 1;
            if(!mark[i] || find(mark[i]))
            {
                mark[i] = x;
                return 1;
            }
        }
    return 0;
}
bool check()
{
    for(int i = 1; i <= n; ++i)
    {
        memset(y, 0, sizeof y);
        if(!find(i)) return 0;
    }
    return 1;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        memset(vis, 0, sizeof vis);
        memset(mark, 0, sizeof mark);
        scanf("%d", &n);
        for(int i = 1, x; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
            {
                scanf("%d", &x);
                if(x) vis[i][j] = 1;
            }
        puts(check() ? "Yes" : "No");
    }
    return 0;
}
--------------------- 
作者:skywalkert 
来源:CSDN 
原文:https://blog.csdn.net/skywalkert/article/details/43955739 
版权声明:本文为博主原创文章,转载请附上博文链接!

https://blog.csdn.net/thy0311/article/details/46963429

猜你喜欢

转载自blog.csdn.net/qiang_____0712/article/details/85917924