• POJ2226 Muddy Fields 二分匹配 最小顶点覆盖 好题


    在一个n*m的草地上,.代表草地,*代表水,现在要用宽度为1,长度不限的木板盖住水,

    木板可以重叠,但是所有的草地都不能被木板覆盖。

    问至少需要的木板数。

    这类题的建图方法:

    把矩阵作为一个二分图,以行列分别作为2个顶点集

    首先以每一行来看,把这一行里面连续的*编号,作为一个顶点

    再以每一列来看,把这一列里面连续的*编号,作为一个顶点

    则每一个*都有2个编号,以行看时有一个,以列看时有一个,则把这2个编号连边,容量为1

    再建一个源点,连接所有行的编号,一个汇点,连接所有列的编号

    这道题要求的是,所有*都被覆盖,即找到一个顶点的集合S,使得任意边都有至少一个顶点属于

    S,即求一个点集顶点覆盖S,又要木板数最少,所以求的就是最小顶点覆盖。

    最小顶点覆盖怎么求?

    二分图中,有:

    最小顶点覆盖=最大匹配

    所以这道题就转化为求二分图的最大匹配了

    再转化为最大流dinic算法。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<queue>
      5 
      6 using namespace std;
      7 
      8 const int maxn=2510;
      9 const int inf=0x3f3f3f3f;
     10 const int s=0;
     11 int t;
     12 int tota;
     13 int totb;
     14 
     15 inline int min(int x,int y)
     16 {
     17     return x<y?x:y;
     18 }
     19 
     20 struct Edge
     21 {
     22     int to,cap,rev;
     23 };
     24 vector<Edge>edge[maxn];
     25 int iter[maxn];
     26 int level[maxn];
     27 char str[55][55];
     28 int hash[55][55];
     29 
     30 void addedge(int from,int to,int cap)
     31 {
     32     edge[from].push_back((Edge){to,cap,edge[to].size()});
     33     edge[to].push_back((Edge){from,0,edge[from].size()-1});
     34 }
     35 
     36 void build_graph(int n,int m)
     37 {
     38     for(int i=0;i<n*m;i++)
     39         edge[i].clear();
     40     tota=0;
     41     for(int i=1;i<=n;i++)
     42     {
     43         int j=1;
     44         while(j<=m)
     45         {
     46             if(str[i][j]=='*')
     47             {
     48                 tota++;
     49                 hash[i][j]=tota;
     50                 while(j<=m&&str[i][j+1]=='*')
     51                 {
     52                     j++;
     53                     hash[i][j]=tota;
     54                 }
     55             }
     56             j++;
     57         }
     58     }
     59     totb=tota;
     60     for(int j=1;j<=m;j++)
     61     {
     62         int i=1;
     63         while(i<=n)
     64         {
     65             if(str[i][j]=='*')
     66             {
     67                 totb++;
     68                 addedge(hash[i][j],totb,1);
     69                 while(i<=n&&str[i+1][j]=='*')
     70                 {
     71                     i++;
     72                     addedge(hash[i][j],totb,1);
     73                 }
     74             }
     75             i++;
     76         }
     77     }
     78     t=tota+totb+1;
     79     for(int i=1;i<=tota;i++)
     80         addedge(s,i,1);
     81     for(int i=tota+1;i<=totb;i++)
     82         addedge(i,t,1);
     83 }
     84 
     85 void bfs()
     86 {
     87     memset(level,-1,sizeof level);
     88     queue<int>que;
     89     while(!que.empty())
     90         que.pop();
     91     que.push(s);
     92     level[s]=1;
     93     while(!que.empty())
     94     {
     95         int u=que.front();
     96         que.pop();
     97         for(int i=0;i<edge[u].size();i++)
     98         {
     99             Edge &e=edge[u][i];
    100             if(e.cap>0&&level[e.to]<0)
    101             {
    102                 level[e.to]=level[u]+1;
    103                 que.push(e.to);
    104             }
    105         }
    106     }
    107 }
    108 
    109 int dfs(int u,int f)
    110 {
    111     if(u==t)
    112         return f;
    113     for(int &i=iter[u];i<edge[u].size();i++)
    114     {
    115         Edge &e=edge[u][i];
    116         if(e.cap>0&&level[e.to]>level[u])
    117         {
    118             int d=dfs(e.to,min(f,e.cap));
    119             if(d>0)
    120             {
    121                 e.cap-=d;
    122                 edge[e.to][e.rev].cap+=d;
    123                 return d;
    124             }
    125 
    126         }
    127     }
    128     return 0;
    129 }
    130 
    131 int solve()
    132 {
    133     int flow=0;
    134     while(true)
    135     {
    136         bfs();
    137         if(level[t]<0)
    138             return flow;
    139         memset(iter,0,sizeof iter);
    140         int f;
    141         while(f=dfs(s,inf))
    142         {
    143             flow+=f;
    144         }
    145     }
    146 }
    147 
    148 int main()
    149 {
    150     int n,m;
    151     while(~scanf("%d%d",&n,&m))
    152     {
    153         for(int i=1;i<=n;i++)
    154         {
    155             scanf("%s",str[i]+1);
    156         }
    157         build_graph(n,m);
    158         printf("%d
    ",solve());
    159     }
    160     return 0;
    161 }
    View Code
  • 相关阅读:
    00077_集合
    python、js、php区别---6、函数相关
    python、js、php区别---5、存储结构
    python、js、php区别---4、基本结构
    python、js、php区别---3、运算符
    python、js、php区别---2、数据类型
    python、js、php区别---1、基本区别
    python疑难问题---3、可变和不可变数据类型
    python疑难问题---2、字典排序
    python疑难问题---1、遍历列表的三种方式
  • 原文地址:https://www.cnblogs.com/-maybe/p/4716460.html
Copyright © 2020-2023  润新知