zoukankan      html  css  js  c++  java
  • BZOJ1059 [ZJOI2007]矩阵游戏 二分图匹配

    1059: [ZJOI2007]矩阵游戏

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 6162  Solved: 2999
    [Submit][Status][Discuss]

    Description

      小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏。矩阵游戏在一个N
    *N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:行交换操作:选择
    矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两列(即交换
    对应格子的颜色)游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑
    色。对于某些关卡,小Q百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!!于是小Q决定写一个程
    序来判断这些关卡是否有解。

    Input

      第一行包含一个整数T,表示数据的组数。接下来包含T组数据,每组数据第一行为一个整数N,表示方阵的大
    小;接下来N行为一个N*N的01矩阵(0表示白色,1表示黑色)。

    Output

      输出文件应包含T行。对于每一组数据,如果该关卡有解,输出一行Yes;否则输出一行No。

    Sample Input

    2
    2
    0 0
    0 1
    3
    0 0 1
    0 1 0
    1 0 0

    Sample Output

    No
    Yes
    【数据规模】
    对于100%的数据,N ≤ 200

     

    一直在想办法dfs+剪枝,后来看了眼BZOJ的一句话题解才意识到是个裸的二分图匹配,行列的最大匹配等于n输出yes,否则输出no

    /**************************************************************
        Problem: 1059
        User: mizersy
        Language: C++
        Result: Accepted
        Time:360 ms
        Memory:2308 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 510;
    int uN,vN;
    int g[MAXN][MAXN];
    int linker[MAXN];
    bool used[MAXN];
    bool dfs(int u)
    {
        for(int v = 0; v < vN; v++)
            if(g[u][v] && !used[v])
            {
                used[v] = true;
                if(linker[v] == - 1 || dfs(linker[v]))
                {
                    linker[v] = u;
                    return true;
                }
            }
        return false;
    }
    int hungary()
    {
        int res = 0;
        memset(linker, - 1,sizeof(linker));
        for(int u = 0; u < uN; u++)
        {
            memset(used,false,sizeof(used));
            if(dfs(u))
                res++;
        }
        return res;
    }
     
    int T,n;
    int main(){
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            uN = vN = n;
            for (int i = 0;i < n;++i)
            {
                for (int j = 0;j < n;++j)
                {
                    scanf("%d",&g[i][j]);
                }
            }
            int ans = hungary();
            if (ans < n) puts("No");else puts("Yes");
        }
    }

    下面是dfs的错误代码:

    /**************************************************************
        Problem: 1059
        User: mizersy
        Language: C++
        Result: Time_Limit_Exceed
    ****************************************************************/
     
    #include <bits/stdc++.h>
    using namespace std;
    int T,n;
    int a[205][205];
    bool r[205],c[205];
    int numr,numc;
    bool vis[205];
    struct Node{
        int r,c;
    };
    bool flag;
    vector <Node> G;
     
    void dfs(int x,int pos,int num)
    {
        if (flag) return;
        if (num == n) {
            flag = true;
            return;
        }
        for (int i = r[x+1];i < G.size();++i)
        {
            Node p = G[i];
            if (p.r > x+1) return;
            if (!vis[p.c]){
                vis[p.c] = 1;
                dfs(p.r,i,num+1);
                vis[p.c] = 0;
            }
        }
    }
     
    int main(){
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            flag = false;
            memset(vis,0,sizeof(vis));
            G.clear();
            memset(r,0,sizeof(r));
            memset(c,0,sizeof(c));
            numr = numc = 0;
            for (int i = 1;i <= n;++i)
            {
                for (int j = 1;j <= n;++j)
                {
                    scanf("%d",&a[i][j]);
                    if (a[i][j] == 1 && !r[i]) r[i] = max((int)G.size(),1),++numr;
                    if (a[i][j] == 1 && !c[j]) c[j] = 1,++numc;
                    if (a[i][j]) G.push_back(Node{i,j});
                }
            }
            if (numr != n || numc != n)
            {
                puts("No");
                continue;
            }
            for (int i = 0;i < G.size();++i)
            {
                if (flag) break;
                Node p = G[i];
                if (p.r > 1) break;
                vis[p.c] = 1;
                dfs(p.r,i,1);
                vis[p.c] = 0;
            }
            if (flag) puts("Yes"); else puts("No");
        }
    }
    View Code
  • 相关阅读:
    进击Node.js基础(一)
    关于bootstrap两个模态框的问题
    系列博文-Three.js入门指南(张雯莉)-网格 setInterval方法 requestAnimationFrame方法 使用stat.js记录FPS
    系列博文-Three.js入门指南(张雯莉)-照相机
    系列博文-Three.js入门指南(张雯莉)-静态demo和three.js功能概览
    for循环执行效率
    c/c++多维数组动态分配与释放
    C/C++数组指针与指针数组详解
    C/C++语言参数传递----值传递、引用传递、指针传递、指针引用传递
    float类型最大值和最小值
  • 原文地址:https://www.cnblogs.com/mizersy/p/9523983.html
Copyright © 2011-2022 走看看