hdu1507——Uncle Tom's Inherited Land*————————【二分圖最大匹配、奇偶分離】

/*

   二分圖最大匹配,同時加上奇偶分離。用匈牙利算法增廣找最大匹配及相互匹配的點對

*/

題目大意:有n*m的一塊兒土地遺產,現在想要賣掉,已知黑格子是池塘不能賣,白格子需要兩塊兒連一起才能賣,問最多能賣多少個這樣的可賣土地。

/**
    劃分奇偶
    二分匹配
    增廣至最大匹配
*/

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXV = 110;
struct node {

    int x, y;
    node() {
        x = 0;
        y = 0;
    }
} match[MAXV][MAXV];
bool G[MAXV][MAXV], vis[MAXV][MAXV];
int f[4][2] = {{0, 1}, {0, -1}, {1, 0}, { -1, 0}};
int n, m;
bool find_AP ( int u, int v )
{

    int x, y;
    for ( int i = 0; i < 4; i++ ) {

        x = u + f[i][0];
        y = v + f[i][1];

        if ( x <= 0 || y <= 0 || x > n || y > m )//界限
            continue;

        if ( !G[x][y] && !vis[x][y] ) { //擴展的那個頂點爲白格子且未曾經過

            vis[x][y] = 1;              //標記
    //如果拓展出的頂點爲未蓋點或該點是匹配點同時該匹配點另一側的匹配點可繼續增廣
            if ( !match[x][y].x || find_AP ( match[x][y].x, match[x][y].y ) ) {

                match[x][y].x = u;      //形成匹配
                match[x][y].y = v;
                return true;
            }
        }
    }

    return false;
}
int main() {

    int k, ans, a, b;

    while ( scanf ( "%d%d", &n, &m ) != EOF && ( n + m ) ) {

        ans = 0;
        memset ( G, 0, sizeof ( G ) );
        memset ( match, 0, sizeof ( match ) );
        for ( int i = 0; i <= n; i++ ) {

            for ( int j = 0; j <= m; j++ ) {

                match[i][j].x = 0;
                match[i][j].y = 0;
            }
        }
        scanf ( "%d", &k );
        for ( int i = 0; i < k; i++ ) {

            scanf ( "%d%d", &a, &b );
            G[a][b] = 1;                    //頂點G[a][b]爲黑格子
        }
        for ( int i = 1; i <= n; i++ ) {

            for ( int j = 1; j <= m; j++ ) {

                memset ( vis, 0, sizeof ( vis ) );//清空標記
                    //如果頂點i,j爲白格子且i+j爲奇數則從該頂點找增廣路
                if ( !G[i][j] && ( ( i + j ) & 1 ) ) {
                    if ( find_AP ( i, j ) )     //如果找到增廣路,即多一條匹配
                        ans++;
                }
            }
        }
        printf ( "%d\n", ans );
        for ( int i = 1; i <= n; i++ ) {

            for ( int j = 1; j <= m; j++ ) {

                if ( ! ( ( i + j ) & 1 ) ) {

                    if ( match[i][j].x != 0 )
                        printf ( "(%d,%d)--(%d,%d)\n", match[i][j].x, match[i][j].y, i, j );
                }
            }
        }
    }
    printf ( "\n" );
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章