1. 程式人生 > >【二分圖】ZJOI2007小Q的遊戲

【二分圖】ZJOI2007小Q的遊戲

格子 scan clas ecn 輸出 每次 他還 顏色 sed

660. [ZJOI2007] 小Q的矩陣遊戲

★☆ 輸入文件:qmatrix.in 輸出文件:qmatrix.out 簡單對比
時間限制:1 s 內存限制:128 MB

【問題描述】 Q是一個非常聰明的孩子,除了國際象棋,他還很喜歡玩一個電腦益智遊戲——矩陣遊戲。矩陣遊戲在一個N*N黑白方陣進行(如同國際象棋一般,只是顏色是隨意的)。每次可以對該矩陣進行兩種操作: l 行交換操作:選擇矩陣的任意兩行,交換這兩行(即交換對應格子的顏色) l 列交換操作:選擇矩陣的任意兩列,交換這兩列(即交換對應格子的顏色) 遊戲的目標,即通過若幹次操作,使得方陣的主對角線(左上角到右下角的連線)上的格子均為黑色。
對於某些關卡,小Q百思不得其解,以致他開始懷疑這些關卡是不是根本就是無解的!!於是小Q決定寫一個程序來判斷這些關卡是否有解。 【輸入文件】 輸入文件qmatrix.in第一行包含一個整數T,表示數據的組數。 接下來包含T組數據,每組數據第一行為一個整數N,表示方陣的大小;接下來N行為一個N*N01矩陣(0表示白色,1表示黑色)。 【輸出文件】 輸出文件應包含T行。對於每一組數據,如果該關卡有解,輸出一行Yes;否則輸出一行No 【樣例輸入】 2 2 0 0 0 1 3 0 0 1
0 1 0 1 0 0 【樣例輸出】 No Yes 【數據規模】 對於20%的數據,N7 對於50%的數據,N50

對於100%的數據,N200

【題解】

這道題乍一看不像能用匈牙利算法

但其實我們仔細觀察一下就能發現,我們可以把為1的點的橫坐標與縱坐標加n連起來

然後看它是否有最大匹配等於n

就能知道可否完成

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

struct
edge{ int to,next; }e[40005]; int T,n,x,ans,ecnt,head[205],point[405]; bool used[4005]; void add(int a,int b) { ecnt++; e[ecnt]=(edge){b+200,head[a]}; head[a]=ecnt; } bool find(int a) { for(int i=head[a];i;i=e[i].next) { if(!used[e[i].to]) { used[e[i].to]=1; if(!point[e[i].to]||find(point[e[i].to])) { point[e[i].to]=a; return true; } } } return false; } int main() { scanf("%d",&T); while(T) { memset(e,0,sizeof(e)); memset(head,0,sizeof(head)); memset(point,0,sizeof(point)); ecnt=0; T--; scanf("%d",&n); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { scanf("%d",&x); if(x)add(i,j); } ans=0; for(int i=1;i<=n;++i) { memset(used,0,sizeof(used)); if(find(i))ans++; } if(ans==n)printf("Yes\n"); else printf("No\n"); } }

【二分圖】ZJOI2007小Q的遊戲