HDU 2819 隐式二分图匹配

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;
}
原文地址:https://www.cnblogs.com/dzzy/p/5230459.html