---恢复内容开始---
https://vjudge.net/problem/POJ-3020
题意
*--代表城市,o--代表空地
给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线。
分析
第一眼看没什么感觉,但要是想到需要处理的点是城市,那这个问题就是一个最小路径覆盖问题了。因为最多覆盖两个城市,即相邻城市才匹配。最小路径覆盖=总节点数-最大匹配数。建图时是双向的,所以最大匹配数/2。
#include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<algorithm> const int MAXN= 500;//最大顶点数 const int MAXM = 11000;//最大边数 const int INF=0x3f3f3f3f; using namespace std; bool g[MAXN][MAXN],used[MAXN]; int linker[MAXN],index[MAXN][MAXN]; int dir[4][2]={{1,0},{0,1},{-1,0},{0,-1}}; int tot; char s[MAXN][MAXN]; bool dfs(int u){ for(int v=0;v<tot;v++){ if(!used[v]&&g[u][v]){ used[v]=true; if(linker[v]==-1||dfs(linker[v])){ linker[v]=u; return true; } } } return false; } int hungry(){ int res=0; memset(linker,-1,sizeof(linker)); for(int i=0;i<tot;i++){ memset(used,false,sizeof(used)); if(dfs(i)) res++; } return res; } int main(){ int t; scanf("%d",&t); while(t--){ int n,m; memset(index,-1,sizeof(index)); memset(g,false,sizeof(g)); scanf("%d%d ",&n,&m); tot=0; for(int i=0;i<n;i++){ gets(s[i]); for(int j=0;j<m;j++){ if(s[i][j]=='*'){ index[i][j]=tot++; } } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(index[i][j]!=-1){ for(int k=0;k<4;k++){ int x=i+dir[k][0]; int y=j+dir[k][1]; if(x>=0&&x<n&&y>=0&&y<m&&index[x][y]!=-1){ g[index[i][j]][index[x][y]]=true; } } } } } int res=hungry(); printf("%d ",tot-res/2); } return 0; }