洛谷 [P1129] [ZJOI2007] 矩阵游戏

这竟然是一道二分图

乍一看,可能是用搜索做,但是这个数据范围,一定会T。
我们观察发现,无论怎样变换,同一行的一定在同一行,同一列的一定还在同一列。所以说,一行只能配一列。这样,我们的目标就是寻找是否存在一种变换方式,使得行数与列数一一对应,且对应数为n。
我们可以把行数和列数作为二分图的两部分,然后跑一个匈牙利

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int init(){
	int rv=0,fh=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-') fh=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		rv=(rv<<1)+(rv<<3)+c-'0';
		c=getchar();
	}
	return rv*fh;
}
int T,n,g[205][205],match[205];
bool f[205];
bool hungarian(int u){
	for(int i=1;i<=g[u][0];i++){
		int v=g[u][i];
		if(!f[v]){
			f[v]=1;
			if(!match[v]||hungarian(match[v])){
				match[v]=u;
				return 1;
			}
		}
	}
	return 0;
}
int main(){
	T=init();
	while(T--){
		n=init();
		memset(g,0,sizeof(g));
		memset(match,0,sizeof(match));
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				int t=init();
				if(t) g[i][++g[i][0]]=j;
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++){
			memset(f,0,sizeof(f));
			if(hungarian(i)) ans++;
		}
		if(ans==n) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}
posted @ 2018-01-09 16:48  Mr_Wolfram  阅读(194)  评论(0编辑  收藏  举报