HDU 2819 Swap

题目大意: 给你一个N代表一个N*N的0-1矩阵,问经过怎样的交换才能使得所有对角线上的值都为一,每次交换只能交换任意的行和列。
若无法交换成功则输出 -1.
 
题目分析:我们把一个图做一次二分匹配,所有的行都匹配到了一个列。若是最大匹配数不能到达n,则说明无论怎么交换都是不能得到对角线全部为一的。当我们匹配完成后,再看每行的匹配值,若是P[i] != i,则进行交换,其实进行的是行交换。在这里可以花个图理解一下。
然后记录交换的过程就是答案了。
 
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 500
int G[maxn][maxn], vis[maxn];
int P[maxn];
int n, m;

bool Find(int u)
{
    for(int i=1; i<=n; i++)
    {
        if(G[u][i] && !vis[i])
        {
            vis[i] = true;
            if(P[i] == -1 || Find(P[i]) )
            {
                P[i] = u;
                return true;
            }
        }
    }
    return false;
}


void solve()
{
    int ans = 0;
    memset(P, -1, sizeof(P));
    for(int i=1; i<=n; i++)
    {
        memset(vis, false, sizeof(vis));
        if(Find(i))
            ans ++;
    }
    if(ans < n)
    {
        puts("-1");
        return ;
    }
    int x[maxn], y[maxn], cnt = 0;
    for(int i=1; i<=n; i++)
    {
        if(P[i] == i)
            continue;
        for(int j=i+1; j<=n; j++)
        {
            if(P[j] == i)
            {
                x[cnt] = P[i];
                y[cnt++] = P[j];
                swap(P[i],P[j]);
                break;
            }
        }
    }
    printf("%d\n", cnt);
    for(int i=0; i<cnt; i++)
        printf("R %d %d\n", x[i], y[i]);
}

int main()
{
    while(scanf("%d",&n) != EOF)
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
                scanf("%d", &G[i][j]);
        }
        solve();
    }
    return 0;
}

/*
3
1 0 1
1 0 1
0 1 0
*/

 

posted @ 2015-08-10 17:18  向前走丶不回首  阅读(202)  评论(0编辑  收藏  举报