最少路径点覆盖=原图点个数-新图最大匹配数
题目链接
题目大意,给出一个图,图由" * " 或"o"组成,现在想要通过覆盖将全部的" * “变成"o”,覆盖规则:每次覆盖相邻的点,问最少需要多少个基站,能覆盖完全。
本题主要是建图,图建完了,匈牙利算法求最大匹配就做完了;
一种新的建图方式,因为直接建图的话,横纵坐标会出现相交的问题,建图错误,通过g将每个“*”编号,根据每一个编号进行建图;建出的图在代码后面;
#include<iostream>
#include<cstring>
using namespace std;
int match[501];
int vis[501];
int path[501][501];
int g[501][501];
int h,m;
int cnt;
void init()
{
memset(path,0,sizeof(path));
memset(g,0,sizeof(g));
memset(match,-1,sizeof(match));
cnt=0;
}
bool fid(int x)
{
for(int i=1; i<=cnt; i++)
{
if(!vis[i]&&path[x][i])
{
vis[i]=1;
if(match[i]==-1||fid(match[i]))
{
match[i]=x;
return true;
}
}
}
return false;
}
int solve()
{
int ans=0;
for(int i=1; i<=cnt; i++)
{
memset(vis,0,sizeof(vis));
if(fid(i)) ans++;
}
return ans;
}
int main()
{
int t;
cin>>t;
while(t--)
{
init();
cin>>h>>m;
string s[50];
for(int i=0; i<h; i++)
cin>>s[i];
for(int i=0; i<h; i++)
for(int j=0; j<m; j++)
if(s[i][j]=='*') g[i][j]=++cnt;
for(int i=0; i<h; i++)
{
for(int j=0 ; j<m; j++)
{
if(g[i][j]>0)
{
if(i!=0)
{
if(g[i-1][j]>0)
path[g[i][j]][g[i-1][j]]=1;
}
if(i!=h-1)
{
if(g[i+1][j]>0)
path[g[i][j]][g[i+1][j]]=1;
}
if(j!=0)
{
if(g[i][j-1]>0)
path[g[i][j]][g[i][j-1]]=1;
}
if(j!=m-1)
{
if(g[i][j+1]>0)
path[g[i][j]][g[i][j+1]]=1;
}
}
}
}
cout<<cnt-solve()/2<<endl;
}
return 0;
}
g的图:
建出的path图: