雖然說是一道水題,但小c覺得還是挺有意思的,所以在這裡mark一下。
第一行包含乙個整數t,表示資料的組數。接下來包含t組資料,每組資料第一行為乙個整數n,表示方陣的大小;接下來n行為乙個n*n的01矩陣(0表示白色,1表示黑色)。
輸出檔案應包含t行。對於每一組資料,如果該關卡有解,輸出一行yes;否則輸出一行no。22
0 00 1
30 0 1
0 1 0
1 0 0
noyes
對於100%的資料,n ≤ 200。
拿到這道題目肯定要思考,什麼樣的局面通過交換行列可以變成主對角線上都為黑格的情況?
由於交換是可逆的,我們倒過來思考,主對角線上都是黑格的情況通過交換行列可以變成什麼局面。
這樣就一目了然了。一開始是1~n的排列,每次交換行列相當於交換兩個位置上的數字。
這樣問題就轉化成:是否能從每行選出恰好乙個黑格,n行黑格代表的列數正好組成乙個1~n的全排列。
正解是二分圖匹配。全排列可以看作是行和列的匹配,思路很清晰。時間複雜度o(n^2)(匈牙利演算法)/o(n^1.5)(網路流)。
但是小c這裡要介紹的,是另一種做法。
想到矩陣和排列,我們會很自然地想起行列式。
我們思考一下行列式的計算公式:
。發現如果乙個排列上的所有數都不為0,就一定會對答案有貢獻!
所以我們就直接求這個矩陣的行列式的值就可以了???複雜度o(n^3)。
當然不行,這些排列對答案的貢獻有正有負,矩陣的值全為0或1的話很容易湊出0。例如,,}。
那怎麼辦?
很簡單啊,我們給矩陣裡的黑格都隨機乙個權值就好了嘛。
什麼?還是wa?
我們來看一看行列式等於0還有什麼條件:
1.有一行或一列全為0的情況;
2.有兩行或兩列數值成比例的情況;
3.行向量之間或列向量之間有相關的情況;
4.逆矩陣不存在的情況:
5.行列式對應的矩陣的秩小於行列式的階數的情況……
夠了!似乎第二條看起來特別扎眼,於是我們給矩陣裡的黑格都隨機乙個質數權值如何?
過了臥槽。
二分圖匹配:
#include #include高斯消元求行列式:#include
#define mn 205
using
namespace
std;
bool
u[mn],mp[mn][mn];
int mat[2
][mn];
intt,n;
inline
intread()
while (c>='
0' && c<='
9')
return n*f;
}bool dfs(int
x) }
return
false;}
intmain()
if (i<=n) puts("
no"); else puts("
yes"
); }
}
#include #include行列式還能這麼用.jpg。#include
#include
#define mod 1000000007
#define mp 2000005
#define mn 205
using
namespace
std;
inta[mn][mn],p[mp];
bool
u[mp];
intt,n,pin;
inline
intread()
while (c>='
0' && c<='
9')
return n*f;
}int mi(int x,int
y)void
init()
}}int
main()
if (i"
no"); else puts("
yes"
); }
}
這題又讓小c了解了一下行列式的一點點性質,好像還練習了一下亂搞技巧?
小c的n^3做法似乎成功拿到了bzoj那一題的墊底:
bzoj1059 矩陣遊戲
time limit 10 sec memory limit 162 mb submit 4731 solved 2255 submit status discuss 矩陣的任意兩行,交換這兩行 即交換對應格仔的顏色 列交換操作 選擇矩陣的任意行列,交換這兩列 即交換 對應格仔的顏色 遊戲的目標,即...
bzoj1059 矩陣遊戲
二分圖匹配經典題。因為每一行的點不管如何交換也不會不在同一行,同理,同一列的點無論如何交換都仍然在這一列。那麼也就是說要選則一些點使得滿足題意,那麼就可以去跑匹配了。若a i j 是黑色的,那麼就從i行向j列連邊,最後跑匹配。如果用邊表的話一定要記得清空計數器。不然就炸了。1 include 2 i...
BZOJ1059 矩陣遊戲
目錄題目傳送門 剛開始理解錯題意了,以為除了主對角線上之外都不能有 後來發現只要主對角線上可以都是 就是合法的了。實際上的題意就是讓你判斷 n 行與 n 列是否可以都匹配上,這樣就是乙個比較簡單的二分圖匹配,如果第 i,j 位置上為 就說明第 i 行與第 j 行能夠匹配,然後跑一遍匈牙利就行了。in...