bzoj1735 [Usaco2005 jan]Muddy Fields 泥泞的牧场

传送门

分析

我们知道对于没有障碍的情况就是将横轴点于纵轴点连边

于是对于这种有障碍的情况我们还是分横轴纵轴考虑

只不过对于有障碍的一整条分为若干个无障碍小段来处理

然后将标号小段连边,跑最大匹配即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int n,m,be1[110][110],be2[110][110],g[3000][3000],Ans,T,used[3000],belong[3000];
char s[110][110];
inline bool work(int x){
    for(int i=1;i<=m;i++)
      if(used[i]!=T&&g[x][i]){
          used[i]=T;
          if(!belong[i]||work(belong[i])){
            belong[i]=x;
            return 1;
        }
      }
    return 0;
} 
inline void go(){
    for(int i=1;i<=n;i++){
      T=i;
      if(work(i))Ans++;
    }
}
int main(){
    int w,r,i,j,k;
    scanf("%d%d",&w,&r);
    for(i=0;i<w;i++)
      scanf("%s",s[i]);
    for(i=0;i<w;i++){
      k=1;
      for(j=0;j<r;j++){
          if(s[i][j]=='.'&&!k)k=1;
          if(s[i][j]=='*'){
            if(k)n++,k=0;
            be1[i][j]=n;
        }
      }
    }
    for(i=0;i<r;i++){
      k=1;
      for(j=0;j<w;j++){
          if(s[j][i]=='.'&&!k)k=1;
          if(s[j][i]=='*'){
            if(k)m++,k=0;
            be2[j][i]=m;
        }
      }
    }
    for(i=0;i<w;i++)
      for(j=0;j<r;j++)
        g[be1[i][j]][be2[i][j]]=1;
    go();
    cout<<Ans;
    return 0;
}