题意:
给出一个矩阵问能否实现对角线全部是1,能的话输出路径,不能的话输出-1
思路:
首先根据矩阵的性质,这一定是一个满秩矩阵,所以只根据行或列交换就一定能实现。
所以行和列构成二分图,然后跑一发匈牙利就知道行不行。
然后怎么输出交换的步骤呢,我们只考虑列交换的话,在对于数组cy[ ]也就是存列的配对对象的数组,对于每个列可以寻找哪个列配对的行是等于他的,因为对角线上行等于列。
如果等于他,而且这个列就是本身他的列,那么这样就好了,如果不是的话就要交换,达到目的,那么还要处理,因为一旦交换他们配对的行就变了。
#include<bits/stdc++.h> using namespace::std; typedef pair<int,int> PII; const int N = 1e2+10; PII swp[1010]; bool rel[N][N]; bool vis[N]; int cy[N],cx[N]; int n; bool FindPath(int u) { for(int v=1;v<=n;v++) { if(vis[v]) continue; if(rel[u][v]) { vis[v]=1; if(cy[v]==-1||FindPath(cy[v])) { cx[u]=v; cy[v]=u; return true; } } } return false; } int main() { while(~scanf("%d",&n)) { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&rel[i][j]); int ans=0; memset(cx,-1,sizeof(cx)); memset(cy,-1,sizeof(cy)); for(int i=1;i<=n;i++) { if(cx[i]==-1){ memset(vis,0,sizeof(vis)); if(FindPath(i)) ans++; } } if(ans==n) { int num=0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(cy[j]==i) { if(i!=j) { swp[num].first=i;swp[num].second=j; swap(cy[i],cy[j]); num++; } break; } } } printf("%d\n",num); for(int i=0;i<num;i++) printf("C %d %d\n",swp[i].first,swp[i].second); } else puts("-1"); } return 0; }