poj 2226 二分图 最小顶点覆盖 “草泥马”

参考地址:http://hi.baidu.com/%BA%A3%CF%E0%C1%AC/blog/item/33dc572f55a1bf4b4fc226a7.html

题意:图中的"*"代表泥泞,"."代表草,要把所以泥泞的地方全铺上板,板可以进行叠加,输出最小的板数。

 一开始看着这道题目,有点儿摸不着头脑,果然像平哥跟龙哥说的那样,这道题的建图模式十分神奇。

      画图画了好久才领略到大牛们的风范。

      例如:

      **...

      *.***

      .****

      .....

      建图的时候先从行开始。相连的那些坑坑洼洼标上相同的数字(有图有真相)

      行:(用数组rr[][]来标识)

         11000

         20333

         04444

         00000

      列:(用数组cc[][]来标识)

         12000

         10456

         03456

         00000

      这就是分开的行列图。不过这里离用匈牙利算法的最小覆盖来解决还差一小步。

      mat[][]数组就是用来标识二分图两边节点的东东。现在转换成mat[rr[i][j]][cc[i][j]]~~这里我之前一直都理解得不是很好,但是画了个图之后,一切都真相大白了。

      画出的图是这样的:

       

     这种行列的构图方式将所有的草地都排除掉了,把坑都连起来的所有可能均建成一个新的图,如上。。太奇妙了……


#include
using namespace std;
int r[2500][2500],c[2500][2500];
bool g[2500][2500];
bool vis[2500];
int link[2500];
char S[55][55];
int nx,ny;
bool dfs(int u)
{
  for(int i=1;i<=ny;i++)
  {
    if(!vis[i]&&g[u][i])
    {
      vis[i]=1;
      if(link[i]==-1||dfs(link[i]))
      {
        link[i]=u;
        return true;
      }
    }
  }
  return false;
}
int maxmatch()
{
  int num=0;
  memset(link,-1,sizeof(link));
  for(int i=1;i<=nx;i++)
  {
    memset(vis,0,sizeof(vis));
    if(dfs(i))  num++;
  }
  return num;
}
int main()
{
  int R,C;
  int  flag; 
  while(scanf("%d%d",&R,&C)!=EOF)
  {
    memset(r,0,sizeof(r));
    memset(c,0,sizeof(c));
    for(int i=0;i>S[i];
    nx=0;
    for(int i=0;i


你可能感兴趣的:(ACM之图论)