Hdu 1507 Uncle Tom's Inherited Land*

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=1507

題意:給一個N*M的矩陣,一個格子表示一塊土地,有些土地被改造成了池塘,問現在如果要按1X2的矩形賣掉土地,最多能賣多少塊,並輸出方案(任一)。

解法:因爲是1X2 的矩陣,所以可以用二分圖做最大匹配來做,構圖時可以將矩陣按行列和的奇偶進行染色,要保證二部圖的建立。

代碼:

//Hdu 1507 二分圖模板。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 10010
int V;
int G[maxn][5]; 
bool map[101][101]; 
class Hungary //模板
{
private:
	int cnt; 
    bool vis[maxn]; 
public:
    int match[maxn]; 
    bool DFS(int u) //搜索增廣路
    {
         for(int v,i = 1; i <= G[u][0]; i++){
             v = G[u][i]; 
             if(!vis[v]){
                 vis[v] = true; 
                 if(match[v] == 0 || DFS(match[v]) ) //如果找到未匹配的結點,則找到了增廣路
                 {
                           match[v] = u;
                           return true;
                 }
             }
         } 
         return false;
    } 
    int Hungary_match()
    {
         cnt = 0;
         memset(match,0,sizeof(match)); 
         for(int u=1; u<=V; u++)
         {
                  memset(vis,0,sizeof(vis)); 
                  if(DFS(u)) cnt++;
         } 
         return cnt;
    }
}H; 
int n,m,k; 
void makeBG()    //奇偶二分建圖
{
	V = n*m; 
    for(int i=1; i<=V; i++)		G[i][0] = 0; 
    int u; 
    for(int i=1; i<=n; i++)
    for(int j=1; j<=m; j++)
    if(map[i][j] && (i+j)%2 == 1)  //奇數
    {
		u = (i-1)*m+j;
		if(map[i][j+1])G[u][ ++G[u][0] ] = u+1;
		if(map[i][j-1])G[u][ ++G[u][0] ] = u-1;
		if(map[i+1][j])G[u][ ++G[u][0] ] = u+m;
		if(map[i-1][j])G[u][ ++G[u][0] ] = u-m;
    }
}
void init(){
	memset(map,1,sizeof(map)); 
	for (int i = 0; i <= n+1; i++)
		map[i][0] = map[i][m+1] = 0;
	for (int i = 0; i <= m+1; i++)
		map[0][i] = map[n+1][i] = 0;
}
int main()
{
	while(~scanf("%d%d",&n,&m),n+m)
    {
		init();
		scanf("%d",&k); 
        int u,v;
        while(k--)
        {
			scanf("%d%d",&u,&v); 
            map[u][v] = 0;
        } 
        makeBG(); 
        printf("%d\n",H.Hungary_match());        
        int link[maxn];
        memset(link,0,sizeof(link)); 
        for(int i=1; i<=V; i++)
                 link[ H.match[i] ] = i; 
        for(int u=1; u<=V; u++)
        if(link[u])
        {
                 v = link[u]; 
				 //找u,v對應的行和列。
                 printf("(%d,%d)",(u-1)/m+1,(u-1)%m+1);
				 printf("--");
				 printf("(%d,%d)",(v-1)/m+1,(v-1)%m+1);
				 printf("\n");
        }
        printf("\n");
    }
    return 0;
}


發佈了119 篇原創文章 · 獲贊 10 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章