poj 3020 Antenna Placement 边覆盖数/最小边覆盖集

题意

  n*m的矩阵中,某些地区需要放置雷达,而雷达覆盖有四种方式,上下左右,问最少的雷达数量覆盖所有*号地区。

 

解法

  关于二分图的性质,有点晕头转向了。 和旭神讨论了。 这个题目是满足二分图的。因为对于一个雷达其关联

的地方分别为上下左右,不能够斜线。则与雷达A关联的其它雷达间是不会有联系的。所以不会形成环。可以转换成

2个集合间的关联关系。所以我们可以通过拆点法求出最大匹配。而有效顶点数量 = 最大匹配数 + 边覆盖数(最小边覆盖集)。 

同时也是本题的所求的边覆盖数,既最小雷达数量。

View Code
#include<cstdio>

#include<cstdlib>

#include<cstring>



const int N = 510;

int match[N], vis[N];

int n, m;



char mp[45][15];

bool edge[N][N];

int dir[4][2] = { {-1,0},{1,0},{0,-1},{0,1} };



int path( int x, int y ){

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

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

            if( edge[ x*m+y ][ i*m+j ] && !vis[i*m+j] ){

                vis[i*m+j] = 1;

                if( (match[ i*m+j ] == -1) || path( match[ i*m+j ]/m, match[ i*m+j ]%m ) ){

                    match[ i*m+j ] = x*m+y;

                    return 1;    

                }    

            }

        }

    return 0;

}

bool legal( int x, int y ){

    if( (x>=0)&&(x<n)&&(y>=0)&&(y<m) ) return true;

    return false;    

}

int main(){

    

    int T;

    scanf("%d",&T);

    while( T-- ){

        scanf("%d%d",&n,&m);

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

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

         memset( edge, 0, sizeof(edge));

         

         int tot = 0;

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

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

                if( mp[i][j] == '*' ){

                    tot++;

                    for(int k = 0; k < 4; k++){

                        int x = i+dir[k][0], y = j+dir[k][1];

                        if( legal(x,y) && (mp[x][y] == '*') )

                            edge[ i*m+j ][ x*m+y ] = 1;

                    }    

                }

            }

        int res = 0;

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

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

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

                if( mp[i][j] == '*' ){ 

                    memset( vis, 0, sizeof(vis));

                    res += path( i, j );

                }

            }    

        }

    //    printf("tot = %d, res = %d\n", tot, res );

        printf("%d\n", tot - res/2 );

//        for(int i = 0; i < n*m; i++)

//            printf("(%d,%d): match = %d\n", i/m, i%m, match[i] );

     }

    return 0;    

}

 

你可能感兴趣的:(ant)