矩陣遊戲 ZJOI2007

2022-05-01 03:51:10 字數 1796 閱讀 2555

行交換操作:選擇矩陣的任意兩行,交換這兩行(即交換對應格仔的顏色)

列交換操作:選擇矩陣的任意兩列,交換這兩列(即交換對應格仔的顏色)

遊戲的目標,即通過若干次操作,使得方陣的主對角線(左上角到右下角的連線)上的格仔均為黑色。

對於某些關卡,小q百思不得其解,以致他開始懷疑這些關卡是不是根本就是無解的!!於是小q決定寫乙個程式來判斷這些關卡是否有解。

第一行包含乙個整數t,表示資料的組數。

接下來包含t組資料,每組資料第一行為乙個整數n,表示方陣的大小;接下來n行為乙個n*n的01矩陣(0表示白色,1表示黑色)。

包含t行。對於每一組資料,如果該關卡有解,輸出一行yes;否則輸出一行no。

輸入樣例#1: 

2

20 0

0 13

0 0 1

0 1 0

1 0 0

輸出樣例#1: 

no

yes

對於20%的資料,n ≤ 7

對於50%的資料,n ≤ 50

對於100%的資料,n ≤ 200

一道不太好建模的二分圖...

首先我們可以發現直接把格仔當做點是不可做的。所以我們考慮把每一列當做乙個點,把每一行當做乙個點。考慮末狀態,可以看做第i行向第i列連了一條匹配邊。行交換操作可以看做匹配邊的交換。

比如(1,4)、(2,3)是黑格仔的話可以看做1->4,2->3連了匹配邊(注意,箭頭左右分屬不同集合,即使數值相同,代表的含義也不同,在**中的編號也是不同的)。那麼交換第一第二行後黑格仔就變成了(1,3)、(2,4),匹配邊為1->3,2->4。可以發現交換x,y兩行就是交換x,y的匹配邊。交換列同理。

所以我們可以得出的乙個結論就是如果想要達到最終狀態,那麼一開始最大匹配數就要等於n.

可以用網路流求最大匹配數。

1 #include2 #include3 #include4 #include5 #include6

#define ll long long

7#define ri register int

8using

namespace

std;

9const

int inf = 0x7ffffff;10

const

int n = 200 + 10;11

const

int m = 1e7 + 10;12

13 inline int

read()

21struct

edge e[m] ;

24int n, s, t, ansf, cnt = 1 ; int head[n<<1], dep[n<<1

] ;25 inline void add_edge(int x,int y,int

ff)

2930 inline bool

f_bfs() 39}

40return

dep[t] ;41}

42int f_dfs(int x,int

minflow)

52return

fflow ;53}

5455

56 inline void

solve() 65}

66}67while(f_bfs()) ansf +=f_dfs(s,inf) ;

68if(ansf == n) printf("

yes\n

") ; else printf("

no\n

") ;69}

7071

intmain()

ZJOI2007 矩陣遊戲

霧。既然我們要求每行每列都要有乙個 1 那麼我們就可以這樣進行建立了這個二分圖。左邊有 n 個點,代表行,右邊有 n 個點,代表列。做這題的主要目的是打板子 二分圖匹配用的dinic bzoj 1059 這裡寫鏈結內容 include include include include include ...

ZJOI2007 矩陣遊戲

我們發現同行同列的點無論經過多少次變換仍然同行或同列,所以題目可轉換為能不能找到n個互相不同行或同列的點。那麼我們用二分圖求一下最大匹配即可。include using namespace std const int n 205 int t,n,x,ans int match n 1 bool vi...

ZJOI2007 矩陣遊戲

這道題是乙個不錯的題,難點就在於建模。交換操作過程中,同一行的黑塊是不會被拆開,同理縱塊也是。接著目標狀態就是一條對角線上全都是黑塊。我們倒過來想,看看能否從目標狀態變成初始狀態。對於所有的黑塊 x,y 左邊行右邊列,點分行列 我們連條邊 x leftarrow rightarrow y 顯然目標狀...