[ZJOI2007]矩阵游戏

https://ac.nowcoder.com/acm/problem/20472

问你能不能通过交换行列的方式使得对角线上全是1

可以这样考虑:

建立二分图,左顶点横坐标,右顶点纵坐标,边就是数字1。

1.当行交换时,相当于左顶点的交换

2.当列交换时,相当于右顶点的交换

所以最好情况就是最大匹配了,最大匹配等于n就能成

具体看代码

#include<iostream>
#include<vector>
using namespace std;
const int maxn = 500+11;
const int N = 202;
vector<int>G[maxn];
void add(int be,int en){
	G[be].push_back(en);
}
int list[maxn][maxn];

int vis[maxn],match[maxn];

int dfs(int x){
	for(int i=0;i<G[x].size();i++){
		int p = G[x][i];
		if(vis[p] == 0){
			vis[p] = 1;
			if(match[p] == 0 || dfs(match[p])){
				match[p] = x;
				return 1;
			}
		}
	}
	return 0;
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		for(int i=0;i<=n;i++){
			G[i].clear();
			G[i+N].clear();
			vis[i] = vis[i+N] = 0;
			match[i] = match[i+N] = 0;
		}
		
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				scanf("%d",&list[i][j]);
				if(list[i][j] == 1){
					add(i,j+N);
					add(j+N,i);
					cout<<i<<" "<<j+N<<endl;
				}
			}
		}
		int ans = 0;
		for(int i=1;i<=n;i++){
			for(int j=0;j<=n;j++){
				vis[j] = vis[j+N] = 0;
			}
			if(dfs(i)) ans++;
		}
		
		if(ans == n){
			cout<<"Yes
";
		}
		else{
			cout<<"No
";
		}
		
	}
	return 0;
} 

  

原文地址:https://www.cnblogs.com/lesning/p/14119346.html