【解题思路】
因为只要验证可行性,所以考虑行和考虑列是等价的,故我们只考虑行的交换操作。
这样,拆一波点,把每一行拆成两个点,左边为原交换行,右边为目标交换行,原问题等价于能否对这个二分图进行完全匹配,题中给定邻接矩阵即为二分图的邻接矩阵。
于是直接匈牙利一波,复杂度O(n3)。
【参考代码】
1 #include <cctype> 2 #include <cstdio> 3 #define REP(I,low,high) for(register int I=(low);I<=(high);I++) 4 #define PER(I,high,low) for(register int I=(high);I>=(low);I--) 5 inline int getint() 6 { 7 char ch=getchar(); 8 for(;!isdigit(ch)&&ch!='+'&&ch!='-';ch=getchar()); 9 bool impositive=ch=='-'; 10 if(impositive) 11 ch=getchar(); 12 int result=0; 13 for(;isdigit(ch);ch=getchar()) 14 result=(result<<3)+(result<<1)+ch-'0'; 15 return impositive?-result:result; 16 } 17 template<typename integer> inline int write(integer n) 18 { 19 integer now=n; 20 bool impositive=now<0; 21 if(impositive) 22 { 23 putchar('-'); 24 now=-now; 25 } 26 char sav[40]; 27 sav[0]=now%10+'0'; 28 int result=1; 29 for(;now/=10;sav[result++]=now%10+'0'); 30 PER(i,result-1,0) 31 putchar(sav[i]); 32 return result+impositive; 33 } 34 //Header Template 35 #include <cstring> 36 bool used[210],map[210][210]; 37 int n,result[210]; 38 bool find(int S) 39 { 40 REP(T,1,n) 41 if(map[S][T]&&!used[T]) 42 { 43 used[T]=true; 44 if(!result[T]||find(result[T])) 45 { 46 result[T]=S; 47 return true; 48 } 49 } 50 return false; 51 } 52 int main() 53 { 54 for(int T=getint();T--;) 55 { 56 n=getint(); 57 REP(i,1,n) 58 REP(j,1,n) 59 map[i][j]=getint(); 60 memset(result,0,sizeof(result)); 61 int ans=0; 62 REP(i,1,n) 63 { 64 memset(used,0,sizeof(used)); 65 ans+=find(i); 66 } 67 puts(ans==n?"Yes":"No"); 68 } 69 return 0; 70 }
We Secure, We Contain, We Protect.