zoukankan      html  css  js  c++  java
  • HDU 1045 Fire Net 【二分图匹配】

    <题目链接>

    题目大意:

    题意思是给出一张图,图中'X'表示wall,'.'表示空地,可以放置炮台,同一条直线上只能有一个炮台,除非有'X'隔开,问在给出的图中最多能放置多少个炮台。

    解题分析:

    本题可用DFS求解 >>> ,但是二分匹配的想法更加巧妙,效率也更高。二分匹配的主要思想就是,对矩阵的行连通块和列连通块进行标号,然后根据矩阵的每个点,建立对应的行连通块和列连通块之间的匹配关系,然后利用匈牙利进行正式匹配,这样当某个行联通块与某个列连通块正式确立匹配关系的时候,说明这两个连通块的交点坐标(之一)放碉堡,而它们的其它部分则不能放碉堡。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 int nrow,ncol;
     7 int g[20][20],linker[20];
     8 bool used[20];
     9 char map[5][5];
    10 int maprow[5][5],mapcol[5][5];
    11 bool dfs(int u){
    12     for(int v=1;v<=ncol;v++)
    13         if(g[u][v]&&!used[v]){
    14             used[v]=true;
    15             if(!linker[v]||dfs(linker[v])){
    16                 linker[v]=u;
    17                 return true;
    18             }    
    19         } 
    20     return false;   
    21 }  
    22 int Hungary(){
    23     int res=0;
    24     memset(linker,0,sizeof(linker));     //将行连通块的归属全部置为空
    25     for(int u=1;u<=nrow;u++){
    26         memset(used,0,sizeof(used));
    27         if(dfs(u))res++;
    28     }   
    29     return res; 
    30 }  
    31 int main(){
    32     int i,j,n;
    33     while(scanf("%d",&n),n){
    34         memset(mapcol,0,sizeof(mapcol));
    35         memset(maprow,0,sizeof(maprow));
    36         memset(g,0,sizeof(g));
    37         for(i=1;i<=n;i++){
    38             for(j=1;j<=n;j++){
    39                 cin>>map[i][j];
    40                 if(map[i][j]=='X')
    41                    mapcol[i][j]=maprow[i][j]=-1;    //X点的行连通编号和列连通编号均标为-1
    42             }  
    43         }
    44         int p1=0;
    45         nrow=0;ncol=0;
    46         //给行编号 
    47         for(i=1;i<=n;i++){
    48             for(j=1;j<=n;j++){              
    49                 while(maprow[i][j]==-1&&j<=n)     //跳过这一行的X部分
    50                     j++;
    51                 p1++;   //p1代表序号
    52                 while(maprow[i][j]!=-1&&j<=n){
    53                       maprow[i][j]=p1;     //给第i行连续的连通块打上相同标号p1  
    54                       if(nrow<p1) nrow=p1;  //记录所有行中,行联通块的最大编号
    55                       j++;
    56                 } 
    57             }
    58         }
    59         int p2=0;
    60         //给列编号 
    61         for(j=1;j<=n;j++)
    62             for(i=1;i<=n;i++){
    63                 while(mapcol[i][j]==-1&&i<=n)    //遍历第j列的时候,跳过X部分
    64                     i++;
    65                 p2++;    
    66                 while(mapcol[i][j]!=-1&&i<=n){
    67                     mapcol[i][j]=p2;    //给第j列的连续的联通块标上相同的序号
    68                     if(ncol<p2)ncol=p2;   //记录下所有列中,列连通块的最大标号
    69                     i++;
    70                 }    
    71             }
    72         for(i=1;i<=n;i++)
    73             for(j=1;j<=n;j++){
    74                 if(maprow[i][j]!=-1&&mapcol[i][j]!=-1)
    75                     g[maprow[i][j]][mapcol[i][j]]=1;     //将每个空格点的行连通标号与列连通标号 构建匹配关系
    76             }
    77         printf("%d
    ",Hungary());            
    78     } 
    79     return 0;   
    80 }

     2018-11-10

  • 相关阅读:
    Intent
    What should we do next in general after collecting relevant data
    NOTE FOR Secure Friend Discovery in Mobile Social Networks
    missing pcap.h
    after building Android Source code
    plot point(one column)
    When talking to someone else, don't infer that is has been talked with others at first. It may bring repulsion to the person who is talking with you.
    进程基本知识
    Python input和raw_input的区别
    强制 code review:reviewboard+svn 的方案
  • 原文地址:https://www.cnblogs.com/00isok/p/9940789.html
Copyright © 2011-2022 走看看