hdu 4185

http://acm.hdu.edu.cn/showproblem.php?pid=4185
题意:给一个二维的地图,地图只有'.'和'#',问最多有多少对‘#’,一对‘#’要相邻。
思路:很明显,是一个二分匹配的题目,当时考虑到600*600个点,不敢写,随后弄了个贪心的算法:
把地图转化成一个无向图,并记录第个点的度。优先匹配度为1的点,再次是度为2的点,度为3和4的点是不会先匹配的,
然后就相当于维护两个队列,并标记每个点是否已被访问和度的变化。
这个想法好像没什么 问题,但一直wa。随后想不出有什么好的二分匹配算法,看解题才知道,居然是裸二分图,orz~~~
PS:这套题的数据好像不是很严谨,前面出了的题目程序还有点小bug,但也过了,hdu这个水库~~~
View Code
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<cmath>
#include<bitset>
#include<string>
#include<climits>
#include<cstdio>
#include<vector>
#include<utility>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define IN puts("in")
#define OUT puts("out")
#define FR(x) freopen(x,"r",stdin)
#define FW(x) freopen(x,"w",stdout)
#define MSET(x,y) memset(x,y,sizeof(x))
#define ST system("pause")
#define lowbit(x) (x)&(-x)
#define L(x) (x)<<1
#define R(x) ((x)<<1)^1
using namespace std;

const int maxn = 605;
char str[maxn][maxn];
int head[maxn*maxn],vis[maxn*maxn],Link[maxn*maxn],st[maxn*maxn];
int n,ecnt,tp;
int dx[] = {1,-1,0,0};
int dy[] = {0,0,-1,1};
struct nd{
    int u,v,next;
}edge[maxn*maxn*5];
bool isok(int x,int y)
{
    if(x==n||y==n||x<0||y<0||str[x][y]!='#')return false;
    return true;
}
void add(int u,int v)
{
    edge[ecnt].u = u;
    edge[ecnt].v = v;
    edge[ecnt].next = head[u];
    head[u] = ecnt++;
}
bool dfs(int u)
{
        int i,v;
        for(i = head[u]; i != -1; i = edge[i].next){
                v = edge[i].v;
                if(vis[v])continue;
                vis[v] = 1;
                st[++tp] = v;
                if(Link[v]==0||dfs(Link[v])){
                        Link[v] = u;
                        return true;
                }
        }return false;
}
int main()
{
    int i,j,k,t,cas=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i = 0; i < n; ++ i)scanf("%s",str[i]);
        memset(head,-1,sizeof(head));
        ecnt = 0;
        for(i = 0; i < n; ++ i)
            for(j = 0; j < n; ++ j)if(str[i][j]=='#')
                for(k = 0; k < 4; ++ k)
                {
                    int x = i + dx[k];
                    int y = j + dy[k];
                    if(isok(x,y))
                        add(i*n+j+1,x*n+y+1);
                }
        k = 0;
        MSET(Link,0);
        for(i = 1; i <= n * n; ++ i){
                MSET(vis,0);
                if(dfs(i))++k;
                while(tp)vis[st[tp--]] = 0;
        }
        printf("Case %d: %d\n",++cas,k/2);
    }
    return 0;
}

 

posted on 2012-07-18 10:34  aigoruan  阅读(202)  评论(0)    收藏  举报

导航