二分图匹配 HDU - 2819输出最大匹配的方案

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2819
题目大意:
给定N * N矩阵,每个条目等于0或1.您可以交换任意两行或任意两列。你能找到一种让所有对角线条目等于1的方法吗?

输入中有几个测试用例。每个测试用例的第一行是整数N(1 <= N <= 100)。然后是N行,每行包含N个数字(0或1),按空格分隔,表示N * N矩阵。

对于每个测试用例,第一行包含交换数M.然后M行跟随,其格式为“R ab”或“C ab”,表示交换行a和行b,或交换列a和列b 。(1 <= a,b <= N)。任何正确答案都将被接受,但是M应该大于1000.

如果不可能使所有对角线条目等于1,则只输出一个包含“-1”的条目。

样本输入
2
0 1
1 0
2
1 0
1 0
样本输出
1
R 1 2
-1

思路:用行与列匹配。如果它可以做到,那么只交换行或者只交换列就可以了。

如果只交换行的话。对于第i行,只考虑第i列,是否存在1,假如:mp[j][i],建图:e[i][j]=1。

然后就是求最大匹配。如果zdl=n,那么就可以。

就是求方案,这零,如果1和2匹配,那么后面有与2匹配,在1和2交换后,现在就是与1匹配了。这点要处理一下。

#include 
using namespace std;

int n,m;//顶点数n和边的数目m
int e[110][110];//保存一个无向图
int book[110];//每次都标记那个去了和那个没去
int match[110];//标记匹配

int dfs (int u)
{
    int i;
    for (i=1;i<=n;i++)
    {
        if (book[i]==0&&e[u][i]==1)//这个点在同一次上没去过,而且他们能联通
        {
            book[i]=1;//这个点已经尝试过了
            if (match[i]==0||dfs(match[i]))//这个点还没有被匹配,
                //或者,他可以匹配其他的人
            {
               //他们就能够匹配
                match[i]=u;//判断哪个,就是修改那个
                //match[u]=i;不用的,错误的
                return 1;
            }
        }
    }
    return 0;
}

int work()
{
    memset(match, 0, sizeof(match));
    int i_count=0;
    for (int i=1;i<=n;i++)//尝试遍历每一个顶点
    {
        memset (book,0,sizeof(book));
        if (dfs(i))
        {
            i_count++;//若能找到新的匹配,就++
        }
    }

    return i_count;
}

int L[10010], R[10010], cut=0;
int main ()
{
    while(~scanf ("%d",&n))
    {
        memset(e, 0, sizeof(e));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&e[i][j]);
            }
        }
        int ans=work();
        if(ans!=n)
        {
            printf("-1\n");
        }
        else
        {
            cut=0;
            for(int i=1;i<=n;i++)
            {
                //cout<<"::::"<
                if(match[i]==i)
                {
                    continue;
                }
                cut++;
                L[cut]=i;
                R[cut]=match[i];
                for(int j=1;j<=n;j++)//当第i行与第match[i]行交换时,所有与i
                //行交换的都相当与match[i]行交换。
                {
                    if(match[j]==i)
                    {
                        swap(match[i], match[j]);
                    }
                }
            }
            printf("%d\n",cut);
            for(int i=1;i<=cut;i++)
            {
                printf("R %d %d\n",L[i], R[i]);
            }
        }
    }

    return 0;
}

/*

3
0 1 0
0 0 1
1 0 0

*/

你可能感兴趣的:(二分图匹配)