poj3020-Antenna Placement-最小点覆盖

来源:互联网 发布:单片机315m无线模块 编辑:程序博客网 时间:2024/05/18 17:25

题意: 每个雷达可以最多覆盖相邻两个城市*  ,询问最少防止几个雷达

思路:

这种类型在 二分图建图方法这篇文章中有讲。因为只能覆盖2个,而这个2 便是建图的依据,枚举点的位置,是否可以同相邻四点建立边, 之后找出最大匹配。

雷达最少的数量,相当于一个点, 就是说用最少的点覆盖所有的城市, 便是一个最小点覆盖的问题:

最小点覆盖= 总点数 - 最大匹配。


#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include <vector>#include<algorithm>using namespace std;const int maxn=1505;int n,m;char mp[maxn][maxn];int pre[maxn];//保存各点的匹配点int vis[maxn];int voc[maxn];int num[maxn][maxn];vector<int> vec[maxn];int find(int u)//判断是否存在增广路,存在返回1{    int i,v;    for(i=0;i<vec[u].size();i++)    {        v=vec[u][i];        if(vis[v])continue;        vis[v]=1;        if(pre[v]==-1||find(pre[v]))//-1找到未盖点,find是增广路。        {            pre[v]=u;//匹配边和非匹配边交换            voc[v]=u;            voc[u]=v;            return 1;        }    }    return 0;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);         memset(pre,-1,sizeof(pre));        memset(num,0,sizeof(num));        memset(mp,0,sizeof(mp));        for(int i=1;i<=n*m;i++)            vec[i].clear();        for(int i=1;i<=n;i++)            scanf("%s",&mp[i][1]);                    int cnt=0;        for(int i=1;i<=n;i++)        {            for(int j=1;j<=m;j++)                if(mp[i][j]=='*')                num[i][j]=++cnt;        }        int data[4][2]={0,1,0,-1,1,0,-1,0};        for(int i=1;i<=n;i++)        {            for(int j=1;j<=m;j++)            {                if(mp[i][j]=='*')                {                    int xi,yi;                    for(int k=0;k<4;k++)                    {                        xi=i+data[k][0],yi=j+data[k][1];                        if(xi<1||xi>n||yi<1||yi>m||mp[i][j]!='*')continue;                        vec[ num[i][j]  ].push_back(num[xi][yi]);                    }                }            }        }        memset(voc,-1,sizeof(voc));        int ans=0;        for(int i=1;i<=cnt;i++)        {            memset(vis,0,sizeof(vis));            ans+=find(i);        }        printf("%d\n",cnt-ans/2);    }    return 0;}


0 0
原创粉丝点击