zoukankan      html  css  js  c++  java
  • ZOJ 1654 匈牙利算法 二分图匹配 Place the Robots

    给每行上的空地编不同号,就算在同一行上,但是被墙壁隔开了的话也编不同的号,一个编号对应一个顶点,这样的顶点放在集合XI中。

    给每列上的空地编不同号,就算在同一行上,但是被墙壁隔开了的话也编不同的号,一个编号对应一个顶点,这样的顶点放在集合YI中。

    如果XI中的某个顶点i和YI中的某个顶点j是在同一个空地上,那么i和j有一条边相连。

    通过如上方法构造出一个二部图(也叫二分图),然后用匈牙利算法做最大二部图匹配,就OK了,我是通过DFS寻找增广路。

    贴代码:

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #define MAXN 55
      4 #define MA 2550
      5 char a[MAXN][MAXN];//输入的地图
      6 int xs[MAXN][MAXN],ys[MAXN][MAXN];//行与列的编号情况
      7 int m,n; //m行,n列
      8 bool g[MA][MA];//记录行编号与列编号的交叉情况
      9 bool s[MA];//DFS时记录是否被访问过
     10 int xx[MA],yy[MA];//记录每个行编号匹配的列编号及列编号匹配的行编号
     11 int X,Y;//行列的最后一个编号,从0开始编
     12 void init()
     13 {
     14     int i,j;
     15     bool flag;
     16     scanf("%d%d",&m,&n);
     17     memset(xs,0xff,sizeof(xs));
     18     memset(ys,0xff,sizeof(ys));
     19     for(i=0; i<m; ++i)  //读入数据
     20         scanf("%s",a[i]);
     21     X=-1;
     22     for(i=0; i<m; ++i)  //给每行没有被墙壁隔开的空地编同一个号,被墙壁隔开编不同号,不同行编不同号
     23     {
     24         flag = false;
     25         for(j=0; j<n; ++j)
     26         {
     27             if(a[i][j] == 'o' )
     28             {
     29                 if(!flag)   X++;
     30                 xs[i][j] = X;
     31                 flag = true;
     32             }
     33             else if(a[i][j] == '#')
     34                 flag = false;
     35         }
     36     }
     37     Y = -1;
     38     for(j=0; j<n; ++j) //给每列编号,同上类似
     39     {
     40         flag = false;
     41         for(i=0; i<m; ++i)
     42         {
     43             if(a[i][j] == 'o')
     44             {
     45                 if(!flag) Y++;
     46                 flag = true;
     47                 ys[i][j] = Y;
     48             }
     49             else if(a[i][j] =='#')
     50                 flag = false;
     51         }
     52     }
     53     memset(g,0,sizeof(g));
     54     for(i=0; i<m; ++i) //如果该空地既有行编号又有列编号,那么编号xs[i][j]与ys[i][j]有边相连
     55         for(j=0; j<n; ++j)
     56             if(xs[i][j] != -1 && ys[i][j] != -1)
     57                 g[xs[i][j]][ys[i][j]] = 1;
     58 }
     59 bool path(int u)
     60 {
     61     int v;
     62     for(v=0; v<=Y; ++v)//考虑所有YI顶点
     63     {
     64         if(g[u][v] && !s[v])//v和u邻接且未访问过
     65         {
     66             s[v] = 1;
     67             if(yy[v] == -1 || path(yy[v]))//V没被匹配过或者V已经被匹配,但能从yy[v]出发找到一条增广路
     68             {
     69                 xx[u] = v;//V匹配给U,U匹配给V
     70                 yy[v] = u;
     71                 return 1;
     72             }
     73         }
     74     }
     75     return 0;
     76 }
     77 void maxMatch()
     78 {
     79     int i,ans =0;
     80     memset(xx,0xff,sizeof(xx));
     81     memset(yy,0xff,sizeof(yy));
     82     for(i=0; i<=X; ++i)//从所有XI中的未盖点出发寻找增广路
     83     {
     84         if(xx[i]==-1)
     85         {
     86             memset(s,0,sizeof(s));
     87             if(path(i))
     88                 ++ans;
     89         }
     90     }
     91     printf("%d\n",ans);
     92 }
     93 int main()
     94 {
     95 //    freopen("in.cpp","r",stdin);
     96     int T;
     97     scanf("%d",&T);
     98     for(int d =1; d<=T; ++d)
     99     {
    100         printf("Case :%d\n",d);
    101         init();
    102         maxMatch();
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    论架构在嵌软设计中的重要性
    妙用typeof关键字
    说说动态内存分配
    3个实用shell脚本,建议收藏!
    GNU C语法扩展(7)
    Ubunt_配置_nfs(文件挂载)
    Ubunt_配置_samba(文件共享)
    Ubunt_配置_tftp(文件传输)
    Ubunt_配置_net
    驱动_Platform平台总线
  • 原文地址:https://www.cnblogs.com/allh123/p/3010909.html
Copyright © 2011-2022 走看看