标签:str 连线 def struct clu ash while += art
题干:
小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏。矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:
行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)
列交换操作:选择矩阵的任意行列,交换这两列(即交换对应格子的颜色)
游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。对于某些关卡,小Q百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!于是小Q决定写一个程序来判断这些关卡是否有解。
题解:
其实这道题我们手模几个满足题干的状态就可知:每一纵列与每一横行的交点(1)一定是独一无二的。
0 0 0 1 0 1 0 0
1 0 0 0 1 0 0 0
0 0 1 0 0 0 0 1
0 1 0 0 0 0 1 0
(上表其余位置均可填1)
比较容易(太难了!!)就可以想到:每个黑点所对应的横纵坐标(x,y)所对应的就是一个二分图。
我们观察这两个表:每个点的横竖都没有黑点(1),或者说,其余的黑点对最终结果不造成任何影响(包括好的或坏的)。
当横纵坐标的值存在一一匹配的情况,就一定有解。
那就用匈牙利算法来解决好了。(都快忘了。。。)
Code:
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #include<queue>
5 #define $ 222
6 using namespace std;
7 int b[$][$],m,n,ans,t,sum,first[$],tot,start[$];
8 bool judge[$];
9 struct tree{ int to,next; }a[$*$];
10 inline void add(int x,int y){
11 a[++tot]=(tree){ y,first[x] };
12 first[x]=tot;
13 /*a[++tot]=(tree){ x,first[y] };
14 first[y]=tot;*/
15 }
16 inline bool km(int x){
17 for(register int i=first[x];i;i=a[i].next){
18 int to=a[i].to;
19 if(judge[to]) continue;
20 judge[to]=1;
21 if(!start[to]||km(start[to])){ start[to]=x; return 1; }
22 }
23 return 0;
24 }
25 inline void work(){
26 memset(a,0,sizeof(a)); ans=tot=0;
27 memset(b,0,sizeof(b));
28 memset(judge,0,sizeof(judge));
29 memset(start,0,sizeof(start));
30 memset(first,0,sizeof(first));
31 scanf("%d",&n);
32 for(register int i=1;i<=n;++i)
33 for(register int j=1;j<=n;++j){
34 scanf("%d",&b[i][j]);
35 b[i][j]?add(i,j),sum+=b[i][j]:1;
36 }
37 if(sum<n){ puts("No"); return; }
38 for(register int i=1;i<=n;++i){
39 memset(judge,0,sizeof(judge));
40 if(km(i)) ++ans;
41 }
42 ans==n?puts("Yes"):puts("No");
43 }
44 signed main(){
45 scanf("%d",&t);
46 while(t--) work();
47 }
标签:str 连线 def struct clu ash while += art
原文地址:https://www.cnblogs.com/OI-zzyy/p/11172178.html