http://acm.hdu.edu.cn/showproblem.php?pid=4185

两个挨着的'#'可以配成一对,求最多能配成几对

挨着的'#'就连边,然后求一次最大匹配,答案是最大匹配除以二(因为1 2和2 1这两对匹配实际效果是1,但是会算成2)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std ;
struct node{
    int s,t,nxt ; 
}e[500005] ;
int m,n,head[500005],cnt,match[500005],vis[500005] ;
int find(int s)
{
    for(int i=head[s] ;i!=-1 ;i=e[i].nxt)
    {
        int tt=e[i].t ;
        if(!vis[tt])
        {
            vis[tt]=1 ;
            if(match[tt]==-1 || find(match[tt]))
            {
                match[tt]=s ;
                return 1 ;
            }
        }
    }
    return 0 ;
}
int max_match()
{
    int ans=0 ;
    memset(match,-1,sizeof(match)) ;
    for(int i=1 ;i<=m ;i++)
    {
        memset(vis,0,sizeof(vis)) ;
        ans+=find(i);
    }
    return ans;
}
void add(int s,int t) {e[cnt].s=s ;e[cnt].t=t ;e[cnt].nxt=head[s] ;head[s]=cnt++ ;}
char M[605][605] ;
int mp[605][605] ;
int dx[]={1,-1,0,0} ;
int dy[]={0,0,1,-1} ;
int main()
{
    int T ;
    scanf("%d",&T) ;
    for(int cas=1 ;cas<=T ;cas++)
    {
        int N ;
        scanf("%d",&N) ;
        for(int i=0 ;i<N ;i++)
            scanf("%s",M[i]) ;
        n=0 ;
        memset(mp,0,sizeof(mp)) ;
        for(int i=0 ;i<N ;i++)
        {
            for(int j=0 ;j<N ;j++)
            {
                if(M[i][j]=='#')
                {
                    n++ ;
                    mp[i][j]=n ;
                }
            }
        }
        memset(head,-1,sizeof(head)) ;
        cnt=0 ;
        for(int i=0 ;i<N ;i++)
        {
            for(int j=0 ;j<N ;j++)
            {
                if(M[i][j]=='#')
                {
                    for(int k=0 ;k<4 ;k++)
                    {
                        int xx=i+dx[k] ;
                        int yy=j+dy[k] ;
                        if(xx<0 || xx>=N || yy<0 || yy>=N)continue ;
                        if(mp[xx][yy])
                        {
                            add(mp[i][j],mp[xx][yy]) ;
                        }
                    }
                }
            }
        }
        m=n ;
        printf("Case %d: %d\n",cas,max_match()/2) ;
    }
    return 0 ;
}
View Code