[ZJOI2007]矩阵游戏-二分图匹配

这个题我们可以从终态入手,

我们发现题目要求的是能否成为使得对角线上都是黑棋。

它具有什么特征呢?那就是保证了每一行每一列存在一个黑点。

那么我们只要能够保证这张图上,至少存在n个点恰好能够覆盖n行n列,那么就一定可以转换成终态。

所以呢怎么判断给定的图是不是满足这个条件呢?

我们把行列分开看,每一个黑棋s[i,j],就对应着第i行和第j列有一条连边。

我们发现,这就相当于一个二分图,而我们只需判断一下这二分图是否存在>=n的匹配就好了。

#include <bits/stdc++.h>
using namespace std;
inline int gi () {
    int x=0, w=0; char ch=0;
    while (!(ch>='0'&&ch<='9')) {
        if (ch=='-') w=1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9') {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    return w?-x:x;
}

int T,n,ans,a[210][210],Vis[210],Guys[210];

bool Hungry (int x) {
    for (int i=1;i<=n;++i) {
        if (Vis[i]||!a[x][i]) continue;
        Vis[i]=1;
        if (!Guys[i]||Hungry(Guys[i])) {
            Guys[i]=x;
            return 1;
        }
    }
    return 0;
}

int main ()
{
    T=gi ();
    while (T--) {
        n=gi ();
        ans=0;
        memset (a,0,sizeof(a));
        memset (Guys,0,sizeof(Guys)); 
        for (int i=1;i<=n;++i)
            for (int j=1;j<=n;++j)
                a[i][j]=gi ();
        for (int i=1;i<=n;++i) {
            memset (Vis,0,sizeof(Vis));
        if (Hungry(i)) ++ans; 
        }
        ans>=n?puts("Yes"):puts("No");
    }
    return 0;
}
BY BHLLX

 

posted @ 2018-11-08 16:28  薄荷凉了夏  阅读(177)  评论(0编辑  收藏  举报