HDU 2819 — Swap 二分匹配

Swap

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2174    Accepted Submission(s): 774
Special Judge


Problem Description
Given an N*N matrix with each entry equal to 0 or 1. You can swap any two rows or any two columns. Can you find a way to make all the diagonal entries equal to 1?
 

 

Input
There are several test cases in the input. The first line of each test case is an integer N (1 <= N <= 100). Then N lines follow, each contains N numbers (0 or 1), separating by space, indicating the N*N matrix.
 

 

Output
For each test case, the first line contain the number of swaps M. Then M lines follow, whose format is “R a b” or “C a b”, indicating swapping the row a and row b, or swapping the column a and column b. (1 <= a, b <= N). Any correct answer will be accepted, but M should be more than 1000.

If it is impossible to make all the diagonal entries equal to 1, output only one one containing “-1”. 
 

 

Sample Input
2 0 1 1 0 2 1 0 1 0
 

 

Sample Output
1 R 1 2 -1
 

 

Source
题意:给定一个n*n的01矩阵;通过行或列的变换使得主对角线上都为1;
题解:  

 1.第i行放到第j行可以使得第j行的主对角线为1;

  2.第j列放到第i列可以使得第j列的主对角线为1;

那么将行作为X集合,列作为Y集合,如果map[i][j]==1,那么Xi->Yj连边,求最大匹配,这样的话没有任何一个行被两个列匹配,

倘若最大匹配为n,即满足题意;

///1085422276
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
typedef long long ll;
using namespace std;
#define inf 10000000
inline ll read()
{
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
//***************************************************************
int lk[101],vis[101],n;
char mp[101][101];
bool dfs(int x){
   for(int i=1;i<=n;i++){
        if(mp[x][i]=='1'&&!vis[i])
        {
            vis[i]=1;
            if(lk[i]==0||dfs(lk[i]))
            {
                lk[i]=x;
                return 1;
            }
        }
   }
   return 0;

}
int main()
{

    while(scanf("%d",&n)!=EOF)
    {int x;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&x);
                mp[i][j]=x+'0';
            }
        }
        memset(lk,0,sizeof(lk));
        int ans=0;
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof(vis));
            if(dfs(i))ans++;
        }
        int flag;
        if(ans<n)printf("-1\n");
        else {
                cout<<n<<endl;
            //for(int i=1;i<=n;i++) cout<<i<<" "<<lk[i]<<endl;
           // for(int i=1;i<=n;i++)flk[lk[i]]=i;
            for(int i=1;i<=n;i++)
            {
               for(int j=i;j<=n;j++)
               {
                   if(lk[j]==i){
                    flag=j;break;
                   }
               }
               lk[flag]=lk[i];
               cout<<"C "<<i<<" "<<flag<<endl;
            }
        }
    }
    return 0;
}
代码

 

转载于:https://www.cnblogs.com/zxhl/p/4759147.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值