【解题思路】

  因为只要验证可行性,所以考虑行和考虑列是等价的,故我们只考虑行的交换操作。

  这样,拆一波点,把每一行拆成两个点,左边为原交换行,右边为目标交换行,原问题等价于能否对这个二分图进行完全匹配,题中给定邻接矩阵即为二分图的邻接矩阵。

  于是直接匈牙利一波,复杂度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 }
View Code