• [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
  • 相关阅读:
    简单数学问题
    MFC 注册表编程
    Windows多线程端口扫描
    MFC Socket双向通信
    凯撒加密
    单片机滤波
    大数素性检验
    大数加法乘法
    Unsafe Code
    委托
  • 原文地址:https://www.cnblogs.com/Bhllx/p/9929882.html
Copyright © 2020-2023  润新知