HDU5093 Battle ships (二分图)

来源:互联网 发布:国际交友软件app 编辑:程序博客网 时间:2024/05/23 14:08

题意:给你一个m*n(1<=m,n<=50)的图,其中 ‘#’代表冰山, ‘*’代表海洋, ‘o’代表浮冰。。然后让你尽可能放置最多的船,但是要满足一下规矩:

  1. 船不能放在冰山上;
  2. 船不能放到浮冰上
  3. 两艘船之间除非中间有冰山,否则不能在同一列或同一行。

分析:红果果的二分最大匹配。。。。图也很容易构造。。。把每一行被冰山分隔开来的海洋格子连通块(至少一个格子)作为X点,同样的每一列被冰山分隔开来的海洋格子连通块作为Y点,X点与Y点有边相连当且仅当这两个连通块共用一个海洋格子。然后跑二分最大匹配。。。2500个点,妥妥的。

以好像是官方题解,但过不了,把next数组改成nextt能过c++的,过不不了g++。

#include<stdlib.h>#include<cmath>#include<cstring>#include<iostream>#include<map>#include<set>#include<algorithm>#include<queue>#include<vector>#include<cstdio>using namespace std;#define N 205#define M 50005int ev[M],nextt[M];int head[M];int cnt;bool vis[M];int pre[M];char s[N][N];int x[N][N],y[N][N];int pn[2];void addedge(int u,int v){    ev[cnt]=v;    nextt[cnt]=head[u];    head[u]=cnt++;    return;}int find(int x){    for(int i=head[x];~i;i=nextt[i]){        int v=ev[i];        if(!vis[v]){            vis[v]=1;            if(pre[v]==-1||find(pre[v]))            {                pre[v]=x;                return 1;            }        }    }    return 0;}int main(){    int t;    scanf("%d",&t);    while(t--){        int n,m;        memset(head,-1,sizeof(head));        cnt=0;        memset(pre,-1,sizeof(pre));        memset(x,0,sizeof(x));        memset(y,0,sizeof(y));        scanf("%d%d",&n,&m);        for(int  i=0;i<n;i++)            scanf("%s",s[i]);        int num=0;        for(int i=0;i<n;i++)        {            bool flag=0;            for(int j=0;j<m;j++){                if(s[i][j]=='*'){                    if(flag==0)                        num++;                    x[i][j]=num;                    flag=1;                }                else if(s[i][j]=='#')                    flag=0;            }        }        pn[0]=num;        num=0;        for(int  i=0;i<m;i++)        {            bool flag=0;            for(int j=0;j<n;j++){                if(s[j][i]=='*'){                    if(flag==0) num++;                    y[j][i]=num;                    flag=1;                }                else if(s[j][i]=='#')                    flag=0;            }        }        pn[1]=num;        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)        {            int u = x[i][j],v=y[i][j];            if(u&&v) addedge(u,v);        }        int ans=0;        for(int i=1;i<=pn[0];++i)        {            memset(vis,0,sizeof(vis));            ans+=find(i);        }        printf("%d\n",ans);    }    return 0;}


0 0