[BZOJ1059][ZJOI2007]矩阵游戏

本文介绍了一种使用二分图最大匹配算法来解决行列交换问题的方法,通过将行号作为左点,列号作为右点,对每个黑点(i,j)连边i到j,然后运行二分图最大匹配算法,判断是否存在完美匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Solution

  由于上一题才做了一道二分图最大匹配的裸题,所以看到这一题就感觉很像二分图最大匹配。

  显然白点不用管,因为不可能有任何贡献。但是行列交换咋整?正向思考受阻,别慌,这题只是判定性问题,我们反向思考。

  假设已经有了一个主对角线都为黑点的矩阵,我们忽略掉矩阵中除主对角线上黑点以外的点,考虑到它一定是经过若干行列交换得来的,于是我们可以手玩一下,把它进行行列交换,随便几次都行。

  然后惊奇地发现不管怎么变换这个矩阵都满足每一行每一列都有且只有一个黑点!(dalao:这不显而易见吗)

  所以直接上套路,行号当左点,列号当右点,对于每个黑点(i,j)连边i到j,跑二分图最大匹配,如果存在完美匹配就是Yes。

  说白了是道水题呀。。。

  Code

#include<bits/stdc++.h>
using namespace std;
const int N=205;
inline int read(){
    char ch=0;
    while(ch!='0'&&ch!='1') ch=getchar();
    return ch^48;
}
bool vis[N],Link[N][N]; 
int n,t,match[N];
bool dfs(int x){
    for(int y=1;y<=n;++y)
        if(!vis[y]&&Link[x][y]){
            vis[y]=true;
            if(!match[y]||dfs(match[y])){
                match[y]=x;
                return true;
            }
        }
    return false;
}
bool hungary(){
    memset(match,0,sizeof match);
    for(int i=1;i<=n;++i){
        memset(vis,0,sizeof vis);
        if(!dfs(i)) return false;
    }
    return true;
}
int main(){
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                Link[i][j]=read();
        puts(hungary()?"Yes":"No"); 
    }        
    return 0;
} 
BZOJ1059

 

  

转载于:https://www.cnblogs.com/gosick/p/11246633.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值