Problem 1015 : Dominating Set

問題概要

重みのない無向グラフで表される都市が与えられる。
グラフの頂点の場所にいくつかスーパーを出店し、どの頂点に住む人も、その頂点または隣の頂点にスーパーがあるような状態にしたい。


このとき、必要なスーパーの数の最小値を求めよ。

解法

グラフのサイズが書いてないが、頂点数≦100として問題なく通った。
これは一般グラフの最小点カバー問題(=最大独立集合に帰着可能)で、NP困難な問題である。


したがって、効率のよいアルゴリズムはないと考えられるので、ここでは枝刈り探索をしてみた。
深さ優先探索で頂点を一つずつ、出店するか出店しないかを決めていき、「その時点でカバーできない辺が出てきてしまっ」たら枝刈り、また、「出店の数が既にわかっている最大値を超えてしまっ」ても枝刈り、としたら0.02sで通った。

ソースコード

int n,m,ans;
vector<vi> e;
bool u[100];

void rec(int c,int use)
{
	if(use>=ans)return;
	
	int p=0;
	for(;p<n;p++)//周りに店がないか調べる
	{
		if(u[p])continue;
		bool cand=0;
		fr(i,e[p])
		{
			if(u[*i])goto NEXT;
			if(*i>=c)cand=1;
		}
		if(!cand)return; else break;
		NEXT:;
	}
	if(p==n)//自分または隣に店のない頂点はない
	{
		ans=min(ans,use); return;
	}
	if(c>=n)return;
	
	rec(c+1,use);
	u[c]=1; rec(c+1,use+1); u[c]=0;
}
int main()
{
	while(scanf("%d%d",&n,&m),n)
	{
		e.clear(); e.resize(n);
		rep(i,n)u[i]=0;
		
		rep(i,m)
		{
			int x,y; scanf("%d%d",&x,&y);
			e[x].pb(y); e[y].pb(x);
		}
		ans=n; rec(0,0);
		printf("%d\n",ans);
	}
	return 0;
}