avatar
fireworks99
keep hungry keep foolish

HDU 2819 Swap(Bipartite graph match)

Description

给出N * N的01矩阵,能否交换行列使得最终主对角线上全为1,不能的话输出-1,能的话输出方案.

Analyze

刚开始想的时候,不明白怎么换,想着什么情况下既要换行又要换列,是那种情况的话该怎么换?越想越复杂。看了题解:

若可以,只换行可行,只换列也可行

二分图最大匹配等于n则可以

DFS(int x)时 link[i] = x;是标记列i被分配给x,是列被标记了!

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;

int n, mp[N][N], link[N];

bool vis[N];
bool DFS(int x)
{
    for(int i = 1; i <= n; ++i)
        if(mp[x][i] && !vis[i])
        {
            vis[i] = 1;
            if(link[i] == -1 || DFS(link[i]))
            {
                link[i] = x;
                return 1;
            }
        }
    return 0;
}

int Match()
{
    int res = 0;
    for(int i = 1; i <= n; ++i)
    {
        memset(vis, 0, sizeof(vis));
        if(DFS(i))
            res++;
    }
    return res;
}

int main()
{
    while(~scanf("%d", &n))
    {
        for(int i = 1; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
                scanf("%d", &mp[i][j]);

        memset(link, -1, sizeof(link));
        int matches = Match();

        if(matches != n)
        {
            cout << "-1\n";
            continue;
        }

        int L[N], R[N], num = 0;
        for(int i = 1; i <= n; ++i)
            if(i != link[i])
                for(int j = 1; j <= n; ++j)
                    if(link[j] == i)
                    {
                        L[num] = i, R[num] = j;
                        num++, swap(link[i], link[j]);
                        break;
                    }
        cout << num << '\n';
        for(int i = 0; i < num; ++i)
            printf("C %d %d\n", L[i], R[i]);
    }
    return 0;
}
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy