码迷,mamicode.com
首页 > 其他好文 > 详细

Swap---hdu2819(最大匹配)

时间:2015-08-10 21:40:56      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:

 

题意:通过交换行或者列来实现对角线(左上角到右下角)上都是1,

首先,如果某行全是0或者某列全是0必然不满足情况输出-1,如果能转换的话,那么必然可以通过全由行(列)变换得到;

还有就是对角线上的N个1,它们各自在不同的行中出现至少一次才可以,

比如样例2中,虽然有两个1,但是它们总是处在同一列,仍然不满足要求,

很明显不能一个行对应两个列,或者说,每一行都应该有至少一个与自己对应的列才能满足条件;

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

如果最大匹配==N,那么必然有解,否则必然无解;

技术分享
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 110

int maps[N][N], vis[N], used[N], n, ans;
int a[10100], b[10100];
bool Find(int u)
{
    for(int i=1; i<=n; i++)
    {
        if(!vis[i] && maps[u][i])
        {
            vis[i] = 1;
            if(!used[i] || Find(used[i]))
            {
                used[i] = u;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    while(scanf("%d", &n)!=EOF)
    {
        memset(used, 0, sizeof(used));
        memset(maps, 0, sizeof(maps));
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                scanf("%d", &maps[i][j]);
            }
        }
        int ans = 0;
        for(int i=1; i<=n; i++)
        {
            memset(vis, 0, sizeof(vis));
            if(Find(i))
                ans++;
        }
        if(ans<n)
        {
            printf("-1\n");
            continue;
        }
        int cnt = 0;
        for(int i=1; i<=n; i++)
        {
            while(used[i]!=i)
            {
                a[cnt] = i;
                b[cnt] = used[i];
                swap(used[a[cnt]], used[b[cnt]]);
                cnt++;
            }
        }
        printf("%d\n", cnt);
        for(int i=0; i<cnt; i++)
            printf("C %d %d\n", a[i], b[i]);
    }
    return 0;
}
View Code

 

Swap---hdu2819(最大匹配)

标签:

原文地址:http://www.cnblogs.com/zhengguiping--9876/p/4719091.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!