建图有些麻烦,把每个最长的1*x作为一个点,建图,跑dinic即可
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<queue> using namespace std; char s[55][55]; int n,m,p1=0,p2=0,S,T,lin[8000],level[8000],ans=0,bel[55][55],len=0,q[8000]; struct one { int y,next,v,reverse; }; one e[100000]; void insert(int xx,int yy) { e[++len].next=lin[xx]; lin[xx]=len; e[len].y=yy; e[len].v=1; e[len].reverse=len+1; e[++len].next=lin[yy]; lin[yy]=len; e[len].y=xx; e[len].v=0; e[len].reverse=len-1; } bool makelevel() { memset(level,-1,sizeof(level)); q[1]=0; level[0]=0; int head=1,tail=1; for(int head=1;head<=tail;head++) { for(int i=lin[q[head]];i;i=e[i].next) { if(level[e[i].y]<0&&e[i].v>0) { level[e[i].y]=level[q[head]]+1; q[++tail]=e[i].y; } } } return level[T]>=0; } int MAXflow(int aa,int flow) { if(aa==T)return flow; int maxflow=0,d=0; for(int i=lin[aa];i&&maxflow<flow;i=e[i].next) { if(e[i].v&&level[e[i].y]==level[aa]+1) { if(d=MAXflow(e[i].y,min(flow-maxflow,e[i].v))) { e[i].v-=d; e[e[i].reverse].v+=d; maxflow+=d; } } } if(maxflow<=0) level[aa]=-1; return maxflow; } void dinic() { int d; while(makelevel()) while(d=MAXflow(0,99999999)) ans+=d; } int main() { while(~scanf("%d%d",&n,&m)) { memset(lin,0,sizeof(lin)); memset(level,0,sizeof(level)); memset(bel,0,sizeof(bel)); p1=0;p2=0; len=0; ans=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>s[i][j]; for(int i=1;i<=n;i++) { int j=1; while(j<=m) { if(s[i][j]=='*') { p1++; bel[i][j]=p1; while(j<=m&&s[i][j+1]=='*') { j++; bel[i][j]=p1; } } j++; } } p2=p1; for(int j=1;j<=m;j++) { int i=1; while(i<=n) { if(s[i][j]=='*') { p2++; insert(bel[i][j],p2); while(i<=n&&s[i+1][j]=='*') { i++; insert(bel[i][j],p2); } } i++; } } S=0;T=p1+p2+1; for(int i=1;i<=p1;i++)insert(S,i); for(int i=1;i<=p2;i++)insert(i+p1,T); dinic(); printf("%d ",ans); } return 0; }