HDU-4185-Oil Skimming [二分匹配]

来源:互联网 发布:空军一号 国际歌 知乎 编辑:程序博客网 时间:2024/05/21 17:59

题目传送门


题意:一个地图由’.’和’#’组成,问有多少个不重叠的’##’。

思路:先将所有的’#’hash,然后建二分图,用匈牙利算法算最大匹配日数,因为边建了两次,所以结果除以二。

#include <algorithm>#include <iostream>#include <cstdlib>#include <cstring>#include <cstdio>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>using namespace std;struct node{    int to, next;}edge[720100];char mp[610][610];int a[610][610];int n, cnt, head[360100];int num;int match[360100];bool used[360100];void add(int u, int v){    edge[cnt].to = v;    edge[cnt].next = head[u];    head[u] = cnt++;}bool Dfs(int x){    for (int i = head[x]; i; i = edge[i].next)    {        int v = edge[i].to;        if (!used[v])        {            used[v] = true;            if (!match[v] || Dfs(match[v]))            {                match[v] = x;                return true;            }        }    }    return false;}int Matching(){    int ans = 0;    memset(match,0,sizeof(match));    for (int i = 1; i <= num; i++)    {        memset(used, false, sizeof(used));        if (Dfs(i))        {            ans++;        }    }    return ans;}int main(void){    //freopen("in.txt", "r", stdin);    //freopen("out.txt", "w", stdout);    int T, cas = 1;    scanf("%d", &T);    while (T--)    {        memset(head, 0, sizeof(head));        memset(a,0,sizeof(a));        memset(mp, 0, sizeof(mp));        cnt = 1;        num = 1;        scanf("%d", &n);        for (int i = 0; i < n; i++)            scanf(" %s", mp[i]);        for (int i = 0; i < n; i++)            for (int j = 0; j < n; j++)                if (mp[i][j]=='#')                    a[i][j] = num++;        num--;        for (int i = 0; i < n; i++)        {            for (int j = 0; j < n; j++)            {                if (a[i][j])                {                    if (i-1>=0 && a[i-1][j])                    {                        add(a[i][j], a[i-1][j]);                    }                    if (i+1<n && a[i+1][j])                    {                        add(a[i][j], a[i+1][j]);                    }                    if (j+1<n && a[i][j+1])                    {                        add(a[i][j], a[i][j+1]);                    }                    if (j-1>=0 && a[i][j-1])                    {                        add(a[i][j], a[i][j-1]);                    }                }            }        }        int ans = Matching();        printf("Case %d: %d\n", cas++, ans/2);    }    return 0;}