http://acm.hdu.edu.cn/showproblem.php?pid=2819
这道题乍一看是矩阵变换题,估计用矩阵之类的也可以做
但是分析一下就可以知道
要凑成对角线都是1,题目允许行变换和列变换
然而观察可以得知如果可以完成只需要行变换或者列变换之一即可
donser[i][j]=1表示i,j位置有1,那么只需要变换j到i(即交换i,j行)
输出中间过程用queue
加上dfs遍历即可
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; int donser[1002][1002]; bool used[1002]; int leave[1002],a[1002],b[1002]; int M,num,abc,j; queue<int >que; void swap(int i,int j) { int t=leave[i];leave[i]=leave[j];leave[j]=t; } int dfs(int x) { for(int i=1;i<=M;i++) { if(donser[x][i]&&!used[i]) { used[i]=true; if(!leave[i]||dfs(leave[i])) { leave[i]=x; return 1; } } } return 0; } int main() { while(~scanf("%d",&M)) { memset(donser,0,sizeof(donser)); memset(leave,0,sizeof(leave)); for(int i=1;i<=M;i++) { for(j=1;j<=M;j++) { scanf("%d",&num); if(num) {donser[i][j]=1;} } } num=abc=0; for(int i=1;i<=M;i++) { memset(used,0,sizeof(used)); if(dfs(i)){abc++;} } if(abc!=M) {cout<<"-1"<<endl;continue;} abc=0,j=1; for(int i=1;i<=M;i++) { for(j=1;j<=M && leave[j]!=i ;j++); if(i!=j) { abc++; que.push(i); que.push(j); swap(i,j); } } cout<<abc<<endl; while(!que.empty()) { cout<<"C "<<que.front(); que.pop(); cout<<" "<<que.front()<<endl; que.pop(); } abc=0; } return 0; }
时间: 2024-10-28 21:58:40