码迷,mamicode.com
首页 > 其他好文 > 详细

[ZJOI2007]矩阵游戏——非常漂亮的二分图转化

时间:2018-07-26 16:20:50      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:--   dfs   nbsp   c++   mes   不能   hit   span   bsp   

题意:

Q 是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个 N×N 黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:

行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)

列交换操作:选择矩阵的任意两列,交换这两列(即交换对应格子的颜色)

游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。

对于某些关卡,小 Q 百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!于是小 Q 决定写一个程序来判断这些关卡是否有解。

样例(1是黑色格子)

2
2
0 0
0 1
3
0 0 1
0 1 0
1 0 0
输出:

No
Yes

 

题解:

 

这个题开始一点儿思路都没有。。。。。

然后偷看了算法标签。。。

二分图???匈牙利算法???

——————醍醐灌顶,恍然大悟,一语惊醒梦中人——————

 

可以观察到:

如果我们能在棋盘上找到形似这样的1的分布:

0 0 1
0 1 0
1 0 0

就是,每行每列有且只有1个1。这就足够了。

其他的1都是跑腿的。

像这样:

0 0 1

1 1 1

0 0 1

虽然1多,但是没用啊。一样不可解。

发现,只要判断是否存在每行每列只有一个1的“有效子图””情况。

这个子图的特点是,一个行和其他所有列的交点上,有且只有一个交点是1,其他都是0

换句话说,一个行和一个列匹配了,就不能和其他的列匹配了!!!!

 

典型的二分图匹配性质!!

我们把所有的行看成是左部点,列看成是右部点,

那么,当这个行和这个列的交点是1的时候,行列之间连一条边。

这里匹配这条边的含义是,有效子图中,在这个位置放一个1。由于匹配的性质,这一行,这一列就不会放其他的1了,和有效子图的定义恰好一致。

看一看最大匹配,是不是n(最大也就是n)

就表明能否找到n个点,满足任意两个点不在同一行,不在同一列上,也就是能构成一个有效子图。

输出yes或者no即可。

 

#include<bits/stdc++.h>
using namespace std;
const int N=200+10;
int t,n;
int pre[N];
int mp[N][N];
struct node{
    int nxt,to;
}e[N*N];
int hd[N],cnt;
void add(int x,int y){
    e[++cnt].nxt=hd[x];
    e[cnt].to=y;
    hd[x]=cnt;
}
bool vis[N];
bool dfs(int x){
    for(int i=hd[x];i;i=e[i].nxt){
        int y=e[i].to;
        if(!vis[y]){
            vis[y]=1;
            if(!pre[y]||dfs(pre[y])){
                pre[y]=x;
                return true;
            }
        }
    }
    return false;
}
void clear(){
    memset(hd,0,sizeof hd);
    cnt=0;
    memset(pre,0,sizeof pre);
}
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        clear();
        for(int i=1;i<=n;i++)
         for(int j=1;j<=n;j++){
             scanf("%d",&mp[i][j]);
             if(mp[i][j]==1) add(i,j);
         }
        int ans=0;
        for(int i=1;i<=n;i++){
            memset(vis,0,sizeof vis);
            if(dfs(i)) ans++;
        }
        if(ans==n){
            printf("Yes\n");
        }
        else printf("No\n");
    }
    return 0;
}

 

[ZJOI2007]矩阵游戏——非常漂亮的二分图转化

标签:--   dfs   nbsp   c++   mes   不能   hit   span   bsp   

原文地址:https://www.cnblogs.com/Miracevin/p/9372088.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!