poj 3020 Antenna Placement

#include <iostream>
using namespace std;
int l,c;

char place[45][15];
int graph[600][600];
int used[600];
int link[600];

int hash[500];
int sum;
void side(int v,int w)  //与相邻点加边到graph图里
{
 int x,y;
 x=hash[v*c+w];
    if ( v >=1 && place[v-1][w]=='*')
 {
   y=hash[(v-1)*c+w];
  graph[x][y]=1;
 
 }
 if (w>=1 && place[v][w-1]=='*' )
 {
  
  y=hash[v*c+w-1];
  graph[x][y]=1;
 
 }
 if (v<=l-2 && place[v+1][w]=='*' )
 {
 
  y=hash[(v+1)*c+w];
  graph[x][y]=1;
  
  
 }
 if (w<=c-2 && place[v][w+1]=='*' )
 {
 
  y=hash[v*c+w+1];
  graph[x][y]=1;
  
 }
 return ;
}

int can(int t)
{
 for (int i=0;i<sum;i++)
  if (!used[i] && graph[t][i])
  {
   used[i]=1;
   if (link[i]==-1 || can(link[i]))
   {
    link[i]=t;
        return 1;
   }
  }
 return 0;
}

int solve()
{
 int num=0,r=0;
 memset(link,-1,sizeof (link));
 for (int i=0;i<sum;i++)
 {
  memset(used,0,sizeof(used));
     if (can(i)) num++;
  else r++;
 }
 return num/2+r;     //因为两边是一样的点,一定出现一条边(正反向)被算两次,所以num要除以2
}
 
   

int main()
{
 int t;
 scanf("%d",&t);

 while(t--)
 {
    
  scanf("%d%d",&l,&c);
  

  for (int i=0;i<l;i++)
    scanf("%s",&place[i]);
  memset(graph,0,sizeof(graph));
     sum=0;
  for (int i=0;i<l;i++)
   for (int j=0;j<c;j++)
    if (place[i][j]=='*')
     hash[i*c+j]=sum++;  //这里hash的技巧很巧妙,把二维的坐标
                                   //转化成一个整数,以作为另一个二维数组的下标hash[i*c+j];

  for (int i=0;i<l;i++)
    for (int j=0;j<c;j++)
   if (place[i][j]=='*')     //把所有相邻的点都映射到graph中的一条边,
     side(i,j);               //最后得到的二分图,其实两边都是一样的点
  printf("%d/n",solve());
 } 
    
               

 return 0;
}

 

你可能感兴趣的:(poj 3020 Antenna Placement)