您的位置:首页 > 其它

poj 2226

2013-12-14 20:04 387 查看
题意:给出一个矩阵 , 每个点代表青草或者泥泞的路 , 问你最少要多少块木板(宽度为一个点的宽度 ,
长度任意)才能把这些泥泞的路都盖住 , 并且不能把草盖住 , 木板可以重合 。

这题要是没加(不能把草盖住)这个条件 , 那么就是普通的最小路径覆盖 。

然而加了这个题之后 , 还是用最小路径覆盖 , 只不过要重新建过图。

最小路径覆盖 = 原图节点数 - 建图后的最大匹配 。

建图:分两步 , 1、从行开始 , 对么个点就行编号 , 如果在同一行并且相邻 , 那么就标记为一个编号 。

               
2、从列开始 , 做法和1一样 , 行跟列是分别单独进行的 。

之后把行构成的点 , 看成是X点集合 , 列看成是Y点集合 , 再根据原图每个点的行跟列进行连接 , 就可以够成一个二分图


最近就只要用最下路径覆盖就能求出了 。

代码:

#include

#include

#include

#include

#include

#include

using namespace std;

const int MAXN = 120;

int n , m ,  pre[2500] , lx[MAXN][MAXN] ,
ly[MAXN][MAXN];

vectorgrap[2500];

bool s[2500];

int x , y;

void init()

{

    for(int i =
0; i <= n; i++)

   
   
grap[i].clear();

    memset(lx ,
0 , sizeof(lx));

    memset(ly ,0
, sizeof(ly));

}

bool can(int u)

{

    for(int i =
0 ; i < grap[u].size(); i++)

    {

   
    int v =
grap[u][i] ;

   
   
if(!s[v])

   
    {

   
   
    s[v] =
true;

   
   
    if(pre[v] ==
-1 || can(pre[v]))

   
   
    {

   
   
   
    pre[v] =
u;

   
   
   
    return
true;

   
   
    }

   
    }

    }

    return
false;

}

int km()

{

    int sum =
0;

    memset(pre ,
-1 , sizeof(pre));

    for(int i =
1; i < x; i++)

    {

   
    memset(s ,
false , sizeof(s));

   
   
if(can(i))  sum += 1;

    }

    return
sum;

}

int main()

{

   
while(scanf("%d %d" , &n , &m) != EOF)

    {

   
   
getchar();

   
   
init();

   
    int
i  ,j ;

   
    x = 1 , y =
1;

   
    char
cy[100][100];

   
    for(i = 0 ;
i < n; i++)

   
    {

   
   
    scanf("%s" ,
cy[i]);

   
   
    for(j = 0 ;
j < m ; j++)

   
   
   
    if(cy[i][j]
== '*')

   
   
   
    {
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: