HDU 1281 棋盤遊戲(二分匹配,關鍵點)

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=69427#problem/E

Description

小希和Gardon在玩一個遊戲:對一個N*M的棋盤,在格子裏放盡量多的一些國際象棋裏面的“車”,並且使得他們不能互相攻擊,這當然很簡單,但是Gardon限制了只有某些格子纔可以放,小希還是很輕鬆的解決了這個問題(見下圖)注意不能放車的地方不影響車的互相攻擊。
所以現在Gardon想讓小希來解決一個更難的問題,在保證儘量多的“車”的前提下,棋盤裏有些格子是可以避開的,也就是說,不在這些格子上放車,也可以保證儘量多的“車”被放下。但是某些格子若不放子,就無法保證放盡量多的“車”,這樣的格子被稱做重要點。Gardon想讓小希算出有多少個這樣的重要點,你能解決這個問題麼?


Input
輸入包含多組數據,
第一行有三個數N、M、K(1<N,M<=100 1<K<=N*M),表示了棋盤的高、寬,以及可以放“車”的格子數目。接下來的K行描述了所有格子的信息:每行兩個數X和Y,表示了這個格子在棋盤中的位置。

Output
對輸入的每組數據,按照如下格式輸出:
Board T have C important blanks for L chessmen.

Sample Input
3 3 4
1 2
1 3
2 1
2 2
3 3 4
1 2
1 3
2 1
3 2

Sample Output
Board 1 have 0 important blanks for 2 chessmen.

Board 2 have 3 important blanks for 3 chessmen.



分析:建邊是根據行和列建的,要找哪些是關鍵點,先求一次最大匹配ans1,然後枚舉哪些條邊刪除,如果刪除了這邊,再求最大匹配ans2,

if(ans2!=ans1)則說明這條邊不能刪,這個點是關鍵點

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int map[105][105],mat[105][105];
int v[105],p[105];
int n,m;
int match(int i)
{
    int j;
    for(j=1;j<=m;j++)
    {
        if(map[i][j]==1&&v[j]==0)
        {
            v[j]=1;
            if(p[j]==-1||match(p[j]))
            {
                p[j]=i;
                return 1;
            }
        }
    }
    return 0;
}
int hungary()
{
    int i,re=0;
    memset(p,-1,sizeof(p));
    for(i=1;i<=n;i++)
    {
        memset(v,0,sizeof(v));
        if(match(i))
        {
            re++;
        }
    }
    return re;
}

int main()
{
    int k,i,a,b,ans,sum,ans1,ji1,t=1,j;
    int pp[105];
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        memset(map,0,sizeof(map));
        for(i=1;i<=k;i++)
        {
            scanf("%d%d",&a,&b);
            map[a][b]=1;
            mat[a][b]=1;

        }
       ans=hungary();
       sum=0;
       for(i=1;i<=104;i++)
       {
           pp[i]=p[i];
       }
       for(j=1;j<=m;j++)
       {
           if(pp[j]!=-1)
           {
               map[pp[j]][j]=0;
               ans1=hungary();
               if(ans1<ans)
                sum++;
            map[pp[j]][j]=1;
           }
       }
      
       printf("Board %d have %d important blanks for %d chessmen.\n",t++,sum,ans);


    }
    return 0;
}




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