BZOJ 1059 矩陣遊戲 (二分圖最大匹配)

題目大意:

小Q是一個非常聰明的孩子,除了國際象棋,他還很喜歡玩一個電腦益智遊戲——矩陣遊戲。矩陣遊戲在一個N*N黑白方陣進行(如同國際象棋一般,只是顏色是隨意的)。每次可以對該矩陣進行兩種操作:行交換操作:選擇矩陣的任意兩行,交換這兩行(即交換對應格子的顏色)列交換操作:選擇矩陣的任意行列,交換這兩列(即交換對應格子的顏色)遊戲的目標,即通過若干次操作,使得方陣的主對角線(左上角到右下角的連線)上的格子均爲黑色。對於某些關卡,小Q百思不得其解,以致他開始懷疑這些關卡是不是根本就是無解的!!於是小Q決定寫一個程序來判斷這些關卡是否有解。


解題思路:

經過發現可得,同行或者同列的黑點,經過任意次變換後依然同行或同列。所以題目可轉換爲能不能找到n個互相不同行或不同列的點。


#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include <map>
#include<vector>
#include<set>
#define LL long long
#define db double
#define EPS 1e-15
#define inf 1e16
#define pa pair<int,int>
 
using namespace std;

int n;
int link[201],mp[201][201];
bool used[201];
bool dfs(int u){
    int v;
    for (v=1;v<=n;v++)
        if (mp[u][v] && !used[v]){
            used[v]=true;
            if (link[v]==-1 ||  dfs(link[v])){
                link[v]=u;
                return true;
            }
        }
    return false;
}
int hungary(){
    int res=0;
    int u;
    memset(link,-1,sizeof(link));
    for (u=1;u<=n;u++){
        memset(used,0,sizeof(used));
        if (dfs(u)) res++;
    }
    return res;
}
int main(){
    int p;
    scanf("%d",&p);
    while (p--){
        memset(link,0,sizeof(link));
        memset(mp,0,sizeof(mp));
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++){
                int x;
                scanf("%d",&x);
                if (x) mp[i][j]=1;
            }
        if (hungary()==n) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}


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