POJ 3020 C++ (图论)

POJ 3020 C++ (图论)

//用算法导论书上最大流做的二分图匹配,所以内存耗的比较大,因为需要队列来存储增广路径
//一个数组没有初始化,wrong了N次
//很多人都是用匈牙利算法做的,偶也准备学学传说中的匈牙利算法
#include<iostream>
using namespace std;
int h,w,flag,res,node;
int arr[500][500],map[50][20];
int q
[10000],pre[10000],used[500];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
int path(int s)  //寻找增广路径
{ int u,head,tail,temp,i,j;
  head=tail=0;
  q[tail++]=s;
  used[s]=1;
  while(head<tail)
       { temp=tail;
         for(i=head;i<temp;i++)
             {    u=q[i];
                  if(u==1)
                     return 1;
                  for(j=0;j<node;j++)
                     if(used[j]==0 && arr[u][j]>0)
                        {pre[j]=u;
                         used[j]=1;
                         q[tail++]=j;
                         }
              }
          head=temp;
       }
  return 0;      
}

void  ford_fulkerson() //修改增光路径上边的残留容量,记录匹配的结果
{ int i,j,u,v,min,x,y;
  min=INT_MAX;
  u=pre[1];
  v=1;
  while(u>=0)
       {if(arr[u][v]<min)
             min=arr[u][v];
            v=u;
            u=pre[u];
       }

  u=pre[1];
  v=1;
  while(u>=0)
       {   arr[u][v]=arr[u][v]-min;
           arr[v][u]=arr[v][u]+min;
           v=u;
           u=pre[u];
        }
   res=res+min;        
}        

int main()
{int i,j,k,Case,x,y;
char c;
       freopen("in.txt","r",stdin);
       freopen("out.txt","w",stdout);
         scanf("%d",&Case);
       while(Case--)  
          { flag=0;
            res=0;
            node=2;
          scanf("%d%d",&h,&w);
          memset(map,0,sizeof(map));
          memset(used,0,sizeof(used));
          memset(arr,0,sizeof(arr));
          for(i=0;i<h;i++)
              {getchar();
               for(j=0;j<w;j++)
                  { scanf("%c",&c);
                    if(c=='*')
                      map[i][j]=node++;
                   }
               }  
           for(i=0;i<h;i++) //构图建模,抽象成二分图匹配的问题
              for(j=0;j<w;j++)
                  { if(map[i][j] && !used[map[i][j]])
                       {  arr[0][map[i][j]]=1;
                          used[map[i][j]]=1;
                          for(k=0;k<4;k++)
                             { x=i+dx[k];
                               y=j+dy[k];
                               if(x>=0 && x<h && y>=0 && y<w && map[x][y])
                               {arr[map[i][j]][map[x][y]]=1;
                                arr[map[x][y]][1]=1;
                                used[map[x][y]]=1;
                               }
                             }
                       }
                  }          
           while(!flag)
             { memset(used,0,sizeof(used));
               memset(pre,-1,sizeof(pre));
               if(path(0))
                  ford_fulkerson();
                else
                  flag=1;
              }
    printf("%d\n",node-2-res);
  }  
   return 0;
}    

你可能感兴趣的:(POJ 3020 C++ (图论))