BZOJ1735: [Usaco2005 jan]Muddy Fields 泥泞的牧场

n<=50 * m<=50的地图,每块地‘*’表示一定要被填上,‘.’表示一定不能填上,用1*l或l*1,l自定,的板填起来,求最少几块板。

如果是做过那种“一炮打一列或一行,求几炮把地图上的点打掉”的二分图经典题,那就可以类比了。不过这里的行和列是基于联通块的,所以预处理出行联通块和列联通块并编号,一个点选,意味着它对应的行联通块和列联通块至少选一个,因此连边。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<algorithm>
  5 //#include<iostream>
  6 using namespace std;
  7 
  8 int n,m;
  9 bool mp[55][55];
 10 char s[55];int belx[55][55],bely[55][55],cntx=0,cnty=0;
 11 #define maxn 5011
 12 #define maxm 5011*4
 13 const int inf=0x3f3f3f3f;
 14 struct Network
 15 {
 16     struct Edge{int to,next,cap,flow;}edge[maxm];int first[maxn],le;
 17     Network() {le=2;memset(first,0,sizeof(first));}
 18     int n,s,t;
 19     void in(int x,int y,int cap) {Edge &e=edge[le];e.to=y;e.cap=cap;e.flow=0;e.next=first[x];first[x]=le++;}
 20     void insert(int x,int y,int cap) {in(x,y,cap);in(y,x,0);}
 21     int que[maxn],head,tail;int dis[maxn],cur[maxn];
 22     bool bfs()
 23     {
 24         que[head=(tail=1)-1]=s;
 25         memset(dis,0,sizeof(dis));dis[s]=1;
 26         while (head!=tail)
 27         {
 28             const int now=que[head++];
 29             for (int i=first[now];i;i=edge[i].next)
 30             {
 31                 const Edge &e=edge[i];
 32                 if (e.cap>e.flow && !dis[e.to])
 33                 {
 34                     dis[e.to]=dis[now]+1;
 35                     que[tail++]=e.to;
 36                 }
 37             }
 38         }
 39         return dis[t];
 40     }
 41     int dfs(int x,int a)
 42     {
 43         if (x==t || !a) return a;
 44         int flow=0,f;
 45         for (int &i=cur[x];i;i=edge[i].next)
 46         {
 47             Edge &e=edge[i];
 48             if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0)
 49             {
 50                 flow+=f;
 51                 e.flow+=f;
 52                 edge[i^1].flow-=f;
 53                 a-=f;
 54                 if (!a) break;
 55             }
 56         }
 57         return flow;
 58     }
 59     int Dinic(int s,int t)
 60     {
 61         this->s=s,this->t=t;
 62         int ans=0;
 63         while (bfs())
 64         {
 65             for (int i=1;i<=n;i++) cur[i]=first[i];
 66             ans+=dfs(s,inf);
 67         }
 68         return ans;
 69     }
 70 }g;
 71 int main()
 72 {
 73     scanf("%d%d",&n,&m);
 74     for (int i=1;i<=n;i++)
 75     {
 76         scanf("%s",s+1);
 77         for (int j=1;j<=m;j++)
 78             mp[i][j]=s[j]=='*';
 79     }
 80     for (int j=1;j<=m;j++)
 81     {
 82         belx[1][j]=mp[1][j]?++cntx:0;
 83         for (int i=2;i<=n;i++)
 84             if (mp[i][j])
 85             {
 86                 if (mp[i-1][j]) belx[i][j]=cntx;
 87                 else belx[i][j]=++cntx;
 88             }
 89             else belx[i][j]=0;
 90     }
 91     for (int i=1;i<=n;i++)
 92     {
 93         bely[i][1]=mp[i][1]?++cnty:0;
 94         for (int j=2;j<=m;j++)
 95             if (mp[i][j])
 96             {
 97                 if (mp[i][j-1]) bely[i][j]=cnty;
 98                 else bely[i][j]=++cnty;
 99             }
100             else bely[i][j]=0;
101     }
102     g.n=cntx+cnty+2;int s=g.n-1,t=g.n;
103     for (int i=1;i<=n;i++)
104         for (int j=1;j<=m;j++)
105             if (mp[i][j]) g.insert(belx[i][j],bely[i][j]+cntx,1);
106     for (int i=1;i<=cntx;i++) g.insert(s,i,1);
107     for (int i=cntx+1;i<=cntx+cnty;i++) g.insert(i,t,1);
108     printf("%d\n",g.Dinic(s,t));
109     return 0;
110 }
View Code

 

posted @ 2017-09-13 14:00  Blue233333  阅读(201)  评论(0编辑  收藏  举报