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;
}