poj 3020 最小路径覆盖

题意:

N * M的矩阵,*代表城市, o代表空地,有四种信号覆盖设备,每种类型信号设备可以覆盖相临得一个点。问要把所有城市覆盖所需最少得设备数?

算法:

1.构图

   关键是怎么构图,如果像poj3041那样以X,Y轴行列号为两个不同得集合,明显行不同,看下答案输出那么大就知道,于是我猜想是否可以用城市构图,

  给城市标号,并且把标号分拆为2个点(vi,vi'), vi为X集合,vi'为Y集合。。然后我发现求出来得二分匹配答案很大,明显又不对。。

而且这里应该是用最少的边覆盖所有点。。。当时不知到有最小路径公式,看了解体报告才知道。发现自己瞎猜得建图正确了。

无向图最小路径 = N - 最大匹配 / 2

证明 http://baike.baidu.com/view/2444809.htm

2.直接用匈牙利算法求出答案

3.总结

   要多看下二分图得概念,不能有知识盲点,了解各公式的证明。

  自己应该思考更长时间,或许可以YY出公式,因为只要想到增加一条匹配边,那么所需要的设备数肯定少1,

  也就是匹配数目与设备数目是相反的,一个递增,另一个就递减。

View Code
//无向图最小路径覆盖
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;

char str[160][160];
int N, M, T, city, maxn;
int hash[5000];
int mp[510][510];
int xx[] = {0, 1, -1, 0};
int yy[] = {1, 0, 0, -1};
int match[510];
bool color[510];

int jugde( int x, int y )
{
 if( x < 1 || x > N || y < 0 || y >= M)
   return 0;
 return 1;
}

void Creat_Graph(int x, int y)
{
   for( int i = 0; i < 4; i++)
   {
      int x1 = x + xx[i];
      int y1 = y + yy[i];
      int a = hash[x * maxn + y];
      int b = hash[x1 * maxn + y1];
      if( jugde(x1, y1) && str[x1][y1] == '*')
      {
         mp[a][b] = 1;
      }

   }
 
}


int find( int x )
{
  for( int i = 1; i <= city; i++)
  {
     if( !color[i] && mp[x][i] )
     {
         color[i] = true;
         if( match[i] == -1 || find( match[i] ))
         {
            match[i] = x;
            return 1;
         }
   
     }

  }
  return 0;
}

void solve( )
{
   int ans = 0;
   memset(match,-1,sizeof(match));
   for( int i = 1; i <= city; i++)
   {
      memset(color, 0, sizeof(color));
      if( find(i) )
    ans++;
   }
   printf("%d\n",city - ans / 2);
}


int main( )
{
  char c[10];
  scanf("%d",&T);
  while(T--)
  {
     scanf("%d%d",&N,&M);
     gets(c);
     city = 0;
     maxn = max( N, M );
     memset(hash, 0, sizeof(hash));
     memset(mp, 0, sizeof(mp));
     for( int i = 1; i <= N; i++)
    gets(str[i]);
     for( int i = 1; i <= N; i++)
     {
        for( int j = 0; j < M; j++)
        {
            if( str[i][j] == '*' )
            {
                ++city;
                hash[i * maxn + j] = city;
            } 

        }

     }
     //构图
     for( int i = 1; i <= N; i++)
     {
        for( int j = 0; j < M; j++)
        {
           if( str[i][j] == '*' )
            Creat_Graph(i, j);

        }

     }
     solve( );

  }
  return 0;
}

posted on 2012-07-14 10:45  more think, more gains  阅读(192)  评论(0编辑  收藏  举报

导航