[BZOJ1059][ZJOI2007]矩阵游戏

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

 

  

posted @ 2019-07-25 20:08  青君  阅读(206)  评论(0编辑  收藏  举报