zoukankan      html  css  js  c++  java
  • hdu2819 Swap 最大匹配(难题)

    题目大意:

      给定一个元素的值只有1或者0的矩阵,每次可以交换两行(列),问有没有方案使得对角线上的值都是1。题目没有限制需要交换多少次,也没限制行交换或者列交换,也没限制是主对角线还是副对角线。虽然没限制,但是解法都是差不多的。

      

      这是09年的多校题目,对一般人来说,不看解题报告是无法做出来的。我是那种看了解题报告也没做出来,然后看了好几遍才看懂的人。

      http://www.cnblogs.com/jzlikewei/archive/2012/07/09/2583608.html

    解题思路:

      对于二分图模型{X,Y| E},我们可以把行作为X集合里的点,把列作为Y集合里的点,边就是值为满足MAP[x][y]=1的条件。判断有没有解就是判断所有的行有没有匹配,也就是最大匹配是否等于n。

      按照顺序输出交换的行(或者是列)是通过而一个二重循环。比如说:从第一行开始,如果它与匹配的列不相等(对角线需要行列相等),就从第二行开始找,直到找到匹配的列等于1。然后把此行匹配的列改为第一行匹配的列。一直下去。因为没有要求最小交换次数的解,所以这样暴力求解就可以了。

      在一般的求最大匹配的模版中,都会有数组cx[],cx[]。其中cx[]记录与X集合匹配的Y集合中元素的标号,cy[]是记录与Y集合匹配的X集合中元素的标号。比如说,cx[3]=2的意思是与X集合中3号元素匹配的Y的集合的元素的编号是2。这两个数组一般情况下只要一个就够的,有些题目就需要输出匹配的序列。

        

    下面的我的代码:Hopcroft-Karp算法,代码有点长,时间复杂度低。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 #include<cmath>
      6 #include<algorithm>
      7 using namespace std;
      8 const int N=105,INF=0x3f3f3f3f;
      9 int cx[N],cy[N],dx[N],dy[N],bmap[N][N];
     10 bool bmask[N];
     11 int nx,ny,dis,ans;
     12 bool searchpath()
     13 {
     14     queue<int> q;
     15     dis=INF;
     16     memset(dx,-1,sizeof(dx));
     17     memset(dy,-1,sizeof(dy));
     18     for(int i=1;i<=nx;i++)
     19     {
     20         if(cx[i]==-1){ q.push(i); dx[i]=0; }
     21         while(!q.empty())
     22         {
     23             int u=q.front(); q.pop();
     24             if(dx[u]>dis) break;
     25             for(int v=1;v<=ny;v++)
     26             {
     27                 if(bmap[u][v]&&dy[v]==-1)
     28                 {
     29                     dy[v]= dx[u] + 1;
     30                     if(cy[v]==-1) dis=dy[v];
     31                     else
     32                     {
     33                         dx[cy[v]]= dy[v]+1;
     34                         q.push(cy[v]);
     35                     }
     36                 }
     37             }
     38         }
     39     }
     40     return dis!=INF;
     41 }
     42 int findpath(int u)
     43 {
     44     for(int v=1;v<=ny;v++)
     45     {
     46         if(!bmask[v]&&bmap[u][v]&&dy[v]==dx[u]+1)
     47         {
     48             bmask[v]=1;
     49             if(cy[v]!=-1&&dy[v]==dis) continue;
     50             if(cy[v]==-1||findpath(cy[v]))
     51             {
     52                 cy[v]=u; cx[u]=v;
     53                 return 1;
     54             }
     55         }
     56     }
     57     return 0;
     58 }
     59 void maxmatch()
     60 {
     61     ans=0;
     62     memset(cx,-1,sizeof(cx));
     63     memset(cy,-1,sizeof(cy));
     64     while(searchpath())
     65     {
     66         memset(bmask,0,sizeof(bmask));
     67         for(int i=1;i<=nx;i++)
     68             if(cx[i]==-1) ans+=findpath(i);
     69     }
     70 }
     71 struct node
     72 {
     73     int x,y;
     74 }e[N];
     75 int main()
     76 {
     77     //freopen("test.txt","r",stdin);
     78     int cas,i,j,k,n;
     79     while(scanf("%d",&n)!=EOF)
     80     {
     81         for(i=1;i<=n;i++)
     82             for(j=1;j<=n;j++)
     83                 scanf("%d",&bmap[i][j]);
     84         nx=ny=n;
     85         maxmatch();
     86         if(ans<n) {printf("-1
    ");continue;}
     87         k=0;
     88         for(i=1;i<=n;i++){
     89             if(cx[i]!=i){
     90                 for(int j=i+1;j<=n;j++){
     91                     if(cx[j]==i){
     92                         e[k].x=i;e[k++].y=j;
     93                         cx[j]=cx[i];
     94                         break;
     95                     }
     96                 }
     97             }
     98         }
     99         printf("%d
    ",k);
    100         for(i=0;i<k;i++)
    101             printf("R %d %d
    ",e[i].x,e[i].y);
    102     }
    103     return 0;
    104 }
    View Code
  • 相关阅读:
    1.2基础--对象属性操作检测遍历
    C语言概览
    测试博客园字体
    c语言指针理解,指针的概念和演示指针的简单操作2
    c语言指针理解代码示例_函数返回指针变量_解除运算符获取指针的值
    c语言指针理解,指针的概念和演示指针的简单操作
    c语言指针概念解释_初步
    项目对文件分目录的感想
    visual studio快捷键
    java开源项目RuoYi若依管理系统
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/3989115.html
Copyright © 2011-2022 走看看