//无向二分图的最小路径覆盖数=顶点总数-最大匹配数/2(最大匹配数=最小点覆盖数) //这里最大匹配数需要除以2,因为每两个相邻的*连一条边,即<u,v>和<v,u>是一样的,所以结果多了一倍 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int MAXN=405; int uN; char G[MAXN][MAXN]; int Hash[MAXN][MAXN]; vector<int> g[MAXN]; int link[MAXN]; bool vis[MAXN]; bool DFS(int u) { for(int i=0;i<g[u].size();i++) { int v=g[u][i]; if(!vis[v]) { vis[v]=true; if(link[v]==-1||DFS(link[v])) { link[v]=u; return true; } } } return false; } int hungary() { int res=0; memset(link,-1,sizeof(link)); for(int u=0;u<uN;u++) { memset(vis,0,sizeof(vis)); if(DFS(u)) res++; } return res; } int main() { int cas,tot; scanf("%d",&cas); while(cas--) { int h,w; tot=0; scanf("%d%d",&h,&w); for(int i=0;i<h;i++) { scanf("%s",G[i]); for(int j=0;j<w;j++) { if(G[i][j]==‘*‘) Hash[i][j]=tot++; //构建数字图 } } memset(g,0,sizeof(g)); for(int i=0;i<h;i++) for(int j=0;j<w;j++) if(G[i][j]==‘*‘) { if(i>0&&G[i-1][j]==‘*‘) g[Hash[i][j]].push_back(Hash[i-1][j]); if(i<h-1&&G[i+1][j]==‘*‘) g[Hash[i][j]].push_back(Hash[i+1][j]); if(j>0&&G[i][j-1]==‘*‘) g[Hash[i][j]].push_back(Hash[i][j-1]); if(j<w-1&&G[i][j+1]==‘*‘) g[Hash[i][j]].push_back(Hash[i][j+1]); } uN=tot; printf("%d\n",tot-hungary()/2); } return 0; }
POJ 3020 Antenna Placement(无向二分图的最小路径覆盖)
原文:http://www.cnblogs.com/atmacmer/p/5201869.html