hdu2819棋盤遊戲(二分圖匹配)

看完這道題,沒什麼思路,只知道求如何求第二問。看了別人題解突然恍然大悟。由於不能放車的地方不影響車的互相攻擊,所以就相當於是列去匹配行,題目中給出的點(x,y),轉化爲g[x}[y}=1(只需要x->y即可),其他位置都是0。而求第一問,就是枚舉每一個點,把它去掉之後再算一遍最大匹配,如果算出來 < ans2,說明它是關鍵點。這種思路和次小生成樹的求法是一樣的,
連暴力枚舉都不會的渣渣=。=|||

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=105;
int n,m;
bool g[MAXN][MAXN];
int x[MAXN*MAXN],y[MAXN*MAXN];
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)
{
    for(int v=0;v<m;v++)
        if(g[u][v]&&!used[v]){
            used[v]=true;
            if(linker[v]==-1||dfs(linker[v])){
                linker[v]=u;
                return true;
            }
        }
    return false;
}
int hungary(void)
{
    int res=0;
    msc(linker);
    for(int u=0;u<n;u++)
    {
        ms(used);
        if(dfs(u)) res++;
    }
    return res;
}
int main(int argc, char const *argv[])
{   
    int k,ti=0;
    while(scanf("%d %d %d",&n,&m,&k)==3)
    {
        ms(g);
        for(int i=0;i<k;i++)
        {
            scanf("%d %d",x+i,y+i);
            x[i]--;
            y[i]--;
            g[x[i]][y[i]]=true;
        }
        int ans1=0,ans2=hungary();
        for(int i=0;i<k;i++)
        {
            g[x[i]][y[i]]=false;
            if(hungary()<ans2) ans1++;
            g[x[i]][y[i]]=true;
        }
printf("Board %d have %d important blanks for %d chessmen.\n",
    ++ti,ans1,ans2);
    }
    return 0;
}
發佈了110 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章