poj3020 Antenna Placement 二分匹配之最小路径覆盖

       题目的意思大致就是,一个矩形中,有N个城市,现在这n个城市都要覆盖无线,若放置一个基站,那么它至多可以覆盖相邻的两个城市。
问至少放置多少个基站才能使得所有的城市都覆盖无线?
构图:行扫描所有城市,编号,如果有城市相邻就连一条边,当然如果3和4相邻,首先graph[3][4]=1,当扫描到4时graph[4][3]也连一条边,最后只需要取一半即可.求最大匹配的一半,这样可以得到所有2个相邻城市被一个基站覆盖所需要的基站数。然后再加上独立的那些基站即可。
公式是:N-最大匹配(代表所有可以和相邻城市配对的城市数)+最大匹配/2=N-最大匹配/2;

Source Code

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
    int nx, ny;             // X的點數目、Y的點數目
int mx[405], my[405];   // X各點的配對對象、Y各點的配對對象
bool vy[405];           // 紀錄Graph Traversal拜訪過的點
bool adj[405][405];     // 精簡過的adjacency matrix
int xx,n,m,cc[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
char g[41][11];
// 以DFS建立一棵交錯樹
bool DFS(int x)
{
    for (int y=0; y<ny; ++y)
        if (adj[x][y] && !vy[y])
        {
            vy[y] = true;

            // 找到擴充路徑
                if (my[y] == -1 || DFS(my[y]))
            {
                mx[x] = y; my[y] = x;
                return true;
               }
        }
    return false;
}

int bipartite_matching()
{
    // 全部的點初始化為未匹配點。
    memset(mx, -1, sizeof(mx));
        memset(my, -1, sizeof(my));

    // 依序把X中的每一個點作為擴充路徑的端點,
    // 並嘗試尋找擴充路徑。
    int c = 0;
    for (int x=0; x<nx; ++x)
//     if (mx[x] == -1)    // x為未匹配點,這行可精簡。
        {
            // 開始Graph Traversal
            memset(vy, false, sizeof(vy));
            if (DFS(x)) c++;
        }
    return c;
}
  void  ini()
{
         int a,b;
         xx=0;
         for(int i=0;i<n;i++)
         for(int j=0;j<m;j++)
         {
           if(g[i][j]=='*')
           {
            xx++;
            a=i*m+j;
            for(int h=0;h<4;h++)
            {
                    if(i+cc[h][0]>=0&&i+cc[h][0]<n&&j+cc[h][1]>=0&&j+cc[h][1]<m&&g[i+cc[h][0]][j+cc[h][1]]=='*')
                    {
                      b=(i+cc[h][0])*m+j+cc[h][1];
                      adj[a][b]=1;
                    }
            }
           }
         }
         nx=ny=m*n;
   }
           
          
main()
{
          int t,i;
         scanf("%d",&t);
         while(t--)
         {
           scanf("%d%d",&n,&m);
           memset(adj, 0, sizeof(adj));
           getchar();
           for(i=0;i<n;i++)
              gets(g[i]);
           ini();
          
           printf("%d\n",xx-bipartite_matching()/2);
         }      
          system("pause");
   }

 

 

 

 
posted @ 2011-02-09 09:02  CoderZhuang  阅读(158)  评论(0编辑  收藏  举报