一些常用性质:
对于无向图:
最小点覆盖+最大独立集=顶点个数
最大团=补图的最大独立子集
关系1:给定图G = (V,E)无孤立点,则G的极大点独立集都是G的极小支配集。
关系2:G的点覆盖数 a与点独立集数 b满足: a + b = n。
关系3:G的边覆盖数 a与边独立集数 b满足: a + b = n。(边独立集数即匹配数)
关系3:给定图G = (V,E)无孤立点,|V | = n。M是G的匹配,W是G的边覆盖,则|M|≤|W|,等号成立时M是G的完美匹配而W是G的最小边覆盖。
对于二部图:
最小点覆盖数 = 最大匹配数
最小路径覆盖 = 顶点数 – 最大(二分)匹配数 / 2;
关于二分图最大匹配,这里讲的很详细http://dsqiu.iteye.com/blog/1689505
关于这道题,其实就是先把“*"看成点,然后看可以覆盖的相邻点,两者相连,接着用上面公式求最小路径覆盖
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <iomanip>
using namespace std;
int mapp[45][15],g[505][505],pp[500],n;
bool visit[500];
int d[4][2]={1,0,0,1,-1,0,0,-1};
bool findd(int x)
{
for(int i=1;i<=n;i++)
{
if(!visit[i]&&g[x][i])
{
visit[i]=1;
if(pp[i]==-1||findd(pp[i]))
{
pp[i]=x;
return true;
}
}
}
return false;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int r,c;
n=0;
cin>>r>>c;
memset(mapp,0,sizeof(mapp));
memset(pp,-1,sizeof(pp));
memset(g,0,sizeof(g));
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
char e;
cin>>e;
if(e=='*')
{
mapp[i][j]=++n;
}
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
if(mapp[i][j])
{
for(int k=0;k<4;k++)
{
int xi=i+d[k][0];
int yi=j+d[k][1];
if(xi>=1&&xi<=r&&yi>=1&&yi<=c&&mapp[xi][yi])
g[mapp[i][j]][mapp[xi][yi]]=1;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(visit,0,sizeof(visit));
if(findd(i))ans++;
}
//cout<<n<<' '<<ans<<endl;
ans=n-(ans/2);
cout<<ans;
cout<<endl;
}
return 0;
}
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <iomanip>
using namespace std;
int mapp[45][15],g[505][505],pp[500],n;
bool visit[500];
int d[4][2]={1,0,0,1,-1,0,0,-1};
bool findd(int x)
{
for(int i=1;i<=n;i++)
{
if(!visit[i]&&g[x][i])
{
visit[i]=1;
if(pp[i]==-1||findd(pp[i]))
{
pp[i]=x;
return true;
}
}
}
return false;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int r,c;
n=0;
cin>>r>>c;
memset(mapp,0,sizeof(mapp));
memset(pp,-1,sizeof(pp));
memset(g,0,sizeof(g));
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
char e;
cin>>e;
if(e=='*')
{
mapp[i][j]=++n;
}
}
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
if(mapp[i][j])
{
for(int k=0;k<4;k++)
{
int xi=i+d[k][0];
int yi=j+d[k][1];
if(xi>=1&&xi<=r&&yi>=1&&yi<=c&&mapp[xi][yi])
g[mapp[i][j]][mapp[xi][yi]]=1;
}
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(visit,0,sizeof(visit));
if(findd(i))ans++;
}
//cout<<n<<' '<<ans<<endl;
ans=n-(ans/2);
cout<<ans;
cout<<endl;
}
return 0;
}