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