ACM POJ 3020 Antenna Placement 二分匹配

来源:互联网 发布:数据库排序 编辑:程序博客网 时间:2024/06/08 07:07

题目链接:http://poj.org/problem?id=3020

题意:相邻两个点可以圈起来,问图中所有的'*'点都被圈起来需要的最小的圈的个数。

分析:1.建二分图;

              图中的点可以二分,

                2.做二分匹配;ans='*'点的个数-最大匹配;

//poj3020#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int maxn=1000;int hash[maxn];int h,w,tot;int f[maxn];//记录当前的映射关系;bool vis[maxn];int a[4][2]={1,0,0,-1,-1,0,0,1};struct edge{    int v,next;}e[maxn*10];void add(int u,int v){    tot++;    e[tot].v=v;    e[tot].next=hash[u];    hash[u]=tot;}int dfs(int p)//点p找到新的匹配,返回1,否则,返回0;{    vis[p]=1;    for (int i=hash[p];i!=-1;i=e[i].next)    {        int v=e[i].v;        int t=f[v];        f[v]=p;        if (!vis[t]&&(t==0||dfs(t))) return 1;        f[v]=t;    }    return 0;}int main(){    //freopen("in.txt","r",stdin);    int T;    cin>>T;    while (T--)    {        cin>>h>>w;        tot=0;        memset(hash,-1,sizeof(hash));        int  s[500][500];        memset(s,0,sizeof(s));        int num=0;        char c;        int ans=0;        while (num<h*w)        {            scanf("%c",&c);            while (c!='*'&&c!='o') scanf("%c",&c);            if (c=='*')            {                s[num/w][num%w]=1;                ans++;            }            num++;        }        for (int i=0;i<h;i++)        for (int j=i%2;j<w;j+=2)        if (s[i][j]==1)        {            for (int k=0;k<4;k++)            {                int x=i+a[k][0],y=j+a[k][1];                if ((x>=0)&&(x<h)&&(y>=0)&&(y<w)&&(s[x][y]==1))                add(i*w+j+1,x*w+y+1);            }        }        memset(f,0,sizeof(f));        for (int i=1;i<=h*w;i++)        {            memset(vis,0,sizeof(vis));            ans-=dfs(i);        }        cout<<ans<<endl;    }}