poj3020_最小覆盖路径(顶点个数-二分图最大匹配数)

来源:互联网 发布:nginx反向代理参数说明 编辑:程序博客网 时间:2024/05/23 22:15

poj3020 题目链接

建议做这题前先做下poj3041题目链接

3041那题是最小点覆盖

3020是最小路径覆盖

题意:

       *--代表城市,o--代表空地

       给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线。

公式:,最小路径覆盖=总节点数-最大匹配数;

但是由于在建图的时候建的是无向图,所以最大匹配数=求得的最大匹配数/2;




首先先找城市,并把城市进行编号1~num,然后在给城市建图MAP_num[];

然后还是用匈牙利算法轻松解决。


关于建图的问题可以再看下poj3026最小生成树问题;

看了一句话:建图是痛苦的,结果的快乐的

#include<stdio.h>#include<string.h>char map[450][450];int num_map[450][450];int MAP_num[450][450]; int res,num,v1,v2;bool v2_vis[450];int v2_link[450];int next[4][2]={{-1,0},{0,1},{1,0},{0,-1}};bool dfs(int x){int y;for(y=1;y<=v2;y++){if(MAP_num[x][y] &&!v2_vis[y]){v2_vis[y]=true;if(v2_link[y]==0 || dfs(v2_link[y])){v2_link[y]=x;return true;}}}return false;}void search(){int x;memset(v2_link,0,sizeof(v2_link));for(x=1;x<=v1;x++){memset(v2_vis,false,sizeof(v2_vis));if(dfs(x))   res++;}}int main(){int T;scanf("%d",&T);while(T--){int n,m,i,j,k;memset(num_map,0,sizeof(num_map));memset(MAP_num,0,sizeof(MAP_num));scanf("%d%d",&n,&m);getchar();for(i=0;i<n;i++)    gets(map[i]);    res=0;num=0;for(i=0;i<n;i++)  for(j=0;j<m;j++)  {  if(map[i][j]=='*')     {     num_map[i][j]=++num;     }  }     v1=v2=num;  for(i=0;i<n;i++)    for(j=0;j<m;j++)        if(num_map[i][j])        {        for(k=0;k<4;k++)        {        int x=i+next[k][0];        int y=j+next[k][1];                if(x<0||x>=n||y<0||y>=m)          continue;                if(num_map[x][y])        {        MAP_num[num_map[i][j]][num_map[x][y]]=1;        }                }        }                search();printf("%d\n",num-res/2);}return 0;} 



0 0
原创粉丝点击