POJ 3020 Antenna Placement(最大二分匹配)

//最大二分匹配(匈牙利算法) //这题实际上是求最小路径覆盖,但根据最小路径覆盖的定义可以将它转化为最大二分匹配 //最小路径覆盖 = |V| - 最大独立集 = |V| - 最大二分匹配 (二分图中最大独立集 = 最大二分匹配) //但是在构图过程中,匹配是双向的,即<u,v> 和<v,u>都算匹配,因此匹配数多了1倍,所以要除以2 //最后得出公式: ans = V + maxMatch/2 #include<iostream> using namespace std; const int MAXN = 45,MAXM = 15; int t,Y,X,U,V; char G[MAXN][MAXM]; int record[MAXN * MAXM]; bool path[MAXN * MAXM][MAXN * MAXM]; bool check[MAXN * MAXM]; int uMatch[MAXN * MAXM],vMatch[MAXN * MAXM]; void searchGraph(int i,int j,int u) { int v; if(G[i][j+1] == '*') { v = record[(i-1)*X + j+1]; path[u][v] = 1; } if(G[i][j-1] == '*') { v = record[(i-1)*X + j-1]; path[u][v] = 1; } if(G[i+1][j] == '*') { v = record[(i)*X + j]; path[u][v] = 1; } if(G[i-1][j] == '*') { v = record[(i-2)*X + j]; path[u][v] = 1; } } void buildGraph()//构图 { for(int i = 1;i <= Y;++i) for(int j = 1;j <= X;++j) { if(G[i][j] == '*') { int u = record[(i-1)*X + j]; searchGraph(i,j,u); } } } bool findPath(int u)//匈牙利算法中的寻找增广路 { for(int v = 1;v <= V;++v) { if(!check[v] && path[u][v]) { check[v] = 1; if(vMatch[v] == -1 || findPath(vMatch[v])) { vMatch[v] = u; uMatch[u] = v; return true; } } } return false; } int maxMatch() { int ans = 0; for(int u = 1;u <= U;++u) { memset(check,0,sizeof(check)); if(findPath(u)) ans++; } return ans; } int main() { //freopen("in.txt","r",stdin); scanf("%d",&t); while(t--) { scanf("%d%d",&Y,&X); getchar();//注意getchar()必须人工将回车吞掉,防止读图错误 //初始化 memset(vMatch,-1,sizeof(vMatch));// memset(uMatch,-1,sizeof(uMatch)); memset(path,0,sizeof(path)); memset(record,-1,sizeof(record)); U = 0; for(int i = 1;i <= Y;++i) { for(int j = 1;j <= X;++j) { G[i][j] = getchar(); if(G[i][j] == '*') { record[(i-1)*X+j] = ++U; } } getchar();//每一行吞掉一个回车 } V = U; buildGraph(); printf("%d/n",U - maxMatch()/2); } return 0; } 

你可能感兴趣的:(算法,Path)