zoukankan      html  css  js  c++  java
  • HDU2819【二分匹配与矩阵的秩】

    题意:

    给出一个矩阵问能否实现对角线全部是1,能的话输出路径,不能的话输出-1

    思路:

    首先根据矩阵的性质,这一定是一个满秩矩阵,所以只根据行或列交换就一定能实现。

    所以行和列构成二分图,然后跑一发匈牙利就知道行不行。

    然后怎么输出交换的步骤呢,我们只考虑列交换的话,在对于数组cy[ ]也就是存列的配对对象的数组,对于每个列可以寻找哪个列配对的行是等于他的,因为对角线上行等于列。

    如果等于他,而且这个列就是本身他的列,那么这样就好了,如果不是的话就要交换,达到目的,那么还要处理,因为一旦交换他们配对的行就变了。

    #include<bits/stdc++.h>
    using namespace::std;
    typedef pair<int,int> PII;
    
    const int N = 1e2+10;
    
    PII swp[1010];
    bool rel[N][N];
    bool vis[N];
    int cy[N],cx[N];
    int n;
    
    bool FindPath(int u)
    {
        for(int v=1;v<=n;v++)
        {
            if(vis[v]) continue;
            if(rel[u][v])
            {
                vis[v]=1;
                if(cy[v]==-1||FindPath(cy[v]))
                {
                    cx[u]=v;
                    cy[v]=u;
                    return true;
                }
            }
        }
        return false;
    }
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&rel[i][j]);
    
            int ans=0;
            memset(cx,-1,sizeof(cx));
            memset(cy,-1,sizeof(cy));
            for(int i=1;i<=n;i++)
            {
                if(cx[i]==-1){
                memset(vis,0,sizeof(vis));
                if(FindPath(i))
                    ans++;
                }
            }
            if(ans==n)
            {
                int num=0;
                for(int i=1;i<=n;i++)
                {
                    for(int j=1;j<=n;j++)
                    {
                        if(cy[j]==i)
                        {
                            if(i!=j)
                            {
                                swp[num].first=i;swp[num].second=j;
                                swap(cy[i],cy[j]);
                                num++;
                            }
                            break;
                        }
                    }
                }
                printf("%d
    ",num);
                for(int i=0;i<num;i++)
                    printf("C %d %d
    ",swp[i].first,swp[i].second);
            }
            else
                puts("-1");
        }
        return 0;
    }
    
    
    


  • 相关阅读:
    在画图时添加中文
    legend图例
    数组的拼接
    将多维数组改为一维数组
    ChinaCock扫描控件介绍-使用TCCBarcodeScanner引起app闪退
    ChinaCock打印控件介绍-TCCFujitsuPrinter实现蓝牙针式打印
    用NetHttpClient执行Post操作遇到的问题
    【转】FireMonkey ListView 自动计算行高
    基于MQTT的串口数据转发器
    kbmMW均衡负载与容灾(1)
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777456.html
Copyright © 2011-2022 走看看