Problem:
Problem G:
Dominating Set
What you have in your hands is a map of Aizu-Wakamatsu City. The lines on this map represent streets and the dots are street corners. Lion Dor Company is going to build food stores at some street corners where people can go to buy food. It is unnecessary and expensive to build a food store on every corner. Their plan is to build the food stores so that people could get food either right there on the corner where they live, or at the very most, have to walk down only one street to find a corner where there was a food store. Now, all they have to do is figure out where to put the food store.
The problem can be simplified as follows. Let
G
= (
V, E
) be unweighted undirected graph. A dominating set
D
of
G
is a subset of
V
such that every vertex in
V
-
D
is adjacent to at least one vertex in
D
. A minimum dominating set is a dominating set of minimum number of vertices for
G
. In the example graph given below, the black vertices are the members of the minimum dominating sets.
Design and implement an algorithm for the minimum domminating set problem.
Input
Input has several test cases. Each test case consists of the number of nodes
n
and the number of edges
m
in the first line. In the following
m
lines, edges are given by a pair of nodes connected by the edge. The graph nodess are named with the numbers 0, 1,...,
n
- 1 respectively.
The input terminate with a line containing two 0. The number of test cases is less than 20.
Constrants
n
≤ 30
m
≤ 50
Output
Output the size of minimum dominating set for each test case.
Sample Input
5 4
0 1
0 4
1 2
3 4
5 4
0 1
0 4
1 2
3 4
0 0
Output for the Sample Input
2
2

Submitted solutions:

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


enum Type{
	UNDEFINED,
	D,
	NOT_D,
};

int N,M,ans;
int min_dist[30];
vector<int> G[30];


bool check(Type array[30]){

	bool FLG;

	for(int i = 0; i < N; i++){

		if(array[i] != NOT_D)continue;

		FLG = false;
		for(int k = 0; k < G[i].size(); k++){
			if(array[G[i][k]] == UNDEFINED || array[G[i][k]] == D){
				FLG = true;
				break;
			}
		}
		if(!FLG)return false;
	}
	return true;
}


void recursive(Type array[30],int num,int count){

	if(count >= ans)return;

	if(num == N){
		ans = count;
		return;
	}

	Type next_arrayD[30];
	for(int i = 0; i < N; i++)next_arrayD[i] = array[i];
	next_arrayD[num] = D;
	recursive(next_arrayD,num+1,count+1);

	Type next_arrayNOT[30];
	for(int i = 0; i < N; i++)next_arrayNOT[i] = array[i];
	next_arrayNOT[num] = NOT_D;
	if(check(next_arrayNOT)){
		recursive(next_arrayNOT,num+1,count);
	}
}


void func(){

	for(int i = 0; i < N; i++){
		G[i].clear();
	}

	int from,to;
	for(int loop = 0; loop < M; loop++){
		scanf("%d %d",&from,&to);
		G[from].push_back(to);
		G[to].push_back(from);
	}

	ans = N;
	Type first[30];
	for(int i = 0; i < N; i++)first[i] = UNDEFINED;

	recursive(first,0,0);

	printf("%d\n",ans);
}

int main(){

	while(true){
		scanf("%d %d",&N,&M);
		if(N == 0 && M == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3276
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int V,E,ans;
ll edge[64];
ll sum_edge[64];
void MDS(int cur,int cost,ll mask){
	if(cost>=ans)return;
	if(mask==(1LL<<V)-1){
		ans=cost;
		return;
	}
	if(cur>=V)return;
	//if((mask|sum_edge[cur])!=(1LL<<V)-1)return;
	MDS(cur+1,cost+1,mask|edge[cur]);
	MDS(cur+1,cost,mask);
}
int main(){
	while(cin>>V>>E,V){
		memset(edge,0,sizeof(edge));
		memset(sum_edge,0,sizeof(sum_edge));
		for(int i=0;i<V;i++)edge[i]|=(1LL<<i);
		for(int i=0;i<E;i++){
			int A,B;
			cin>>A>>B;
			edge[A]|=(1LL<<B);
			edge[B]|=(1LL<<A);
		}
		for(int i=V-1;i>=0;i--) sum_edge[i] |= edge[i];
		for(int i=V-2;i>=0;i--) sum_edge[i] |= sum_edge[i+1];
		ans=1e9;
		MDS(0,0,0);
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 30
memory_kb: 3104
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int V,E,ans;
ll edge[64];
ll sum_edge[64];
void MDS(int cur,int cost,ll mask){
	if(cost>=ans)return;
	if(mask==(1LL<<V)-1){
		ans=min(ans,cost);
		return;
	}
	if(cur>=V)return;
	//if((mask|sum_edge[cur])!=(1LL<<V)-1)return;
	MDS(cur+1,cost+1,mask|edge[cur]);
	MDS(cur+1,cost,mask);
}
int main(){
	while(cin>>V>>E,V){
		memset(edge,0,sizeof(edge));
		memset(sum_edge,0,sizeof(sum_edge));
		for(int i=0;i<V;i++)edge[i]|=(1LL<<i);
		for(int i=0;i<E;i++){
			int A,B;
			cin>>A>>B;
			edge[A]|=(1LL<<B);
			edge[B]|=(1LL<<A);
		}
		for(int i=V-1;i>=0;i--) sum_edge[i] |= edge[i];
		for(int i=V-2;i>=0;i--) sum_edge[i] |= sum_edge[i+1];
		ans=1e9;
		MDS(0,0,0);
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 50
memory_kb: 3016
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int V,E,ans;
ll edge[64];
ll sum_edge[64];
void MDS(int cur,int cost,ll mask){
	if(cost>=ans)return;
	if(mask==(1LL<<V)-1){
		ans=min(ans,cost);
		return;
	}
	if(cur>=V)return;
	//if((mask|sum_edge[cur])!=(1LL<<V)-1)return;
	MDS(cur+1,cost,mask);
	MDS(cur+1,cost+1,mask|edge[cur]);
}
int main(){
	while(cin>>V>>E,V){
		memset(edge,0,sizeof(edge));
		memset(sum_edge,0,sizeof(sum_edge));
		for(int i=0;i<V;i++)edge[i]|=(1LL<<i);
		for(int i=0;i<E;i++){
			int A,B;
			cin>>A>>B;
			edge[A]|=(1LL<<B);
			edge[B]|=(1LL<<A);
		}
		for(int i=V-1;i>=0;i--) sum_edge[i] |= edge[i];
		for(int i=V-2;i>=0;i--) sum_edge[i] |= sum_edge[i+1];
		ans=1e9;
		MDS(0,0,0);
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 140
memory_kb: 3060
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int V,E,ans;
ll edge[64];
ll sum_edge[64];
void MDS(int cur,int cost,ll mask){
	if(cost>=ans)return;
	if(mask==(1LL<<V)-1){
		ans=min(ans,cost);
		return;
	}
	if(cur>=V)return;
	//if((mask|sum_edge[cur])!=(1LL<<V)-1)return;
	MDS(cur+1,cost+1,mask|edge[cur]);
	MDS(cur+1,cost,mask);
	//MDS(cur+1,cost+1,mask|edge[cur]);
}
int main(){
	while(cin>>V>>E,V){
		memset(edge,0,sizeof(edge));
		memset(sum_edge,0,sizeof(sum_edge));
		for(int i=0;i<V;i++)edge[i]|=(1LL<<i);
		for(int i=0;i<E;i++){
			int A,B;
			cin>>A>>B;
			edge[A]|=(1LL<<B);
			edge[B]|=(1LL<<A);
		}
		for(int i=V-1;i>=0;i--) sum_edge[i] |= edge[i];
		for(int i=V-2;i>=0;i--) sum_edge[i] |= sum_edge[i+1];
		ans=1e9;
		MDS(0,0,0);
		cout<<ans<<endl;
	}
}
accuracy: 1
time_ms: 40
memory_kb: 3076
final_rank: 15

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#define REP(i,s,n) for(int i=(int)(s);i<(int)(n);i++)

using namespace std;
typedef long long int ll;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef pair<int, int> PI;
const ll mod = 1e9 + 7;

int mi = 10000;

void dfs(int x, int v, int vs, int cov, const vector<int> &links) {
  if (v >= x) {
    return;
  }
  if (mi <= __builtin_popcount(vs)) {
    return;
  }
  //cout << "dfs(" << x << "," << v << "," << vs << ")" << endl;
  // cover without v
  if (links[v] != 0) {
    dfs(x, v + 1, vs, cov, links);
  }
  //cover with v
  vs |= 1 << v;
  cov |= 1 << v;
  cov |= links[v];
  if (cov == (1 << x) - 1) {
    mi = min(mi, __builtin_popcount(vs));
    return;
  }
  REP(i, v + 1, x) {
    if (vs & (1 << i)) {
      continue;
    }
    dfs(x, i, vs, cov, links);
    break;
  }
  return;
}


int solve(int x, const vector<PI> &edges, const VI &links) {
  ll es = 0;
  mi = x;
  dfs(x, 0, 0, 0, links);
  return mi;
}


int main(void){
  int x, y;
  while (cin >> x >> y && (x || y)) {
    vector<PI> edges;
    vector<int> link(x);
    REP(i, 0, y) {
      int a, b;
      cin >> a >> b;
      edges.push_back(PI(a, b));
      link[a] |= 1 << b;
      link[b] |= 1 << a;
    }
    cout << solve(x, edges, link) << endl;
  }
}
accuracy: 1
time_ms: 230
memory_kb: 3020
final_rank: 18

code_snippet: #include <cstdio>
#include <algorithm>

#define rep(i, n) for(int i = 0; i < n; ++i)

using namespace std;

int x, y;
int g[30][30];
bool b[30];

bool dfs(int i, int k){
	if(i == x){
		if(k != 0){
			return false;
		}

		rep(j, x){
			if(b[j]){
				continue;
			}

			bool f = false;
			rep(k, x){
				if(b[k] && g[j][k]){
					f = true;
					break;
				}
			}
			if(!f){
				return false;
			}
		}
		return true;
	}
	else if(k == 0){
		b[i] = 0;
		return dfs(i + 1, k);
	}
	else{
		b[i] = 0;
		bool f = dfs(i + 1, k);
		if(f){
			return true;
		}
		b[i] = 1;
		return dfs(i + 1, k - 1);
	}
}

int main(){
	while(1){
		scanf("%d%d", &x, &y);
		if(x == 0 && y == 0){
			break;
		}

		rep(i, y){
			int a, b;
			scanf("%d%d", &a, &b);
			g[a][b] = g[b][a] = 1;
		}

		for(int k = 1; k <= x; ++k){
			if(dfs(0, k)){
				printf("%d\n", k);
				break;
			}
		}

		rep(i, 30){
			rep(j, 30){
				g[i][j] = 0;
			}
		}
	}
	return 0;
}
accuracy: 1
time_ms: 290
memory_kb: 1028
final_rank: 1

code_snippet: #include <iostream>
#include <vector>
using namespace std;

int c_neighbor[31];             // c???closed neighbor

// Check whether a set dset of size k is a dominating set of a graph
// of n vertices.
bool is_dominating_set(int dset, int n)
{
  int dominated = 0;
  for (int v=0;v<n;v++)
  {
    if (dset % 2)              // v???dset?????????
    {
      dominated |= c_neighbor[v];
    }
    dset = dset >> 1;
  }
  if (dominated == (1<<n)-1) return true;
  else return false;
}

int main()
{
  int n, m;
  int u, v;
  while (cin >> n >> m)
  {
    bool found = false;

    if (n == 0) return 0;
    for (int i=0;i<n;i++) c_neighbor[i]=1<<i;
    for (int i=0;i<m;i++)
    {
      cin >> u >> v;
      c_neighbor[u] |= (1<<v);
      c_neighbor[v] |= (1<<u);
    }

    int dset;
    for (int k=1;k<=n;k++)
    {
      // {0,...,n-1}?????¨???????????§????????????k??§???????????????????????????
      // ????????°???????????°????????????????????£??¬???????????????????????§
      dset = (1 << k) - 1;
      while (dset < 1<<n)
      {
        if (is_dominating_set(dset, n))
        {
          cout << k << endl;
          found = true;
        }
        if (found) break;

        int x = dset & -dset;
        int y = dset + x;
        dset = ((dset & ~y) / x >> 1) | y;
      }
      if (found) break;
    }
  }
}
accuracy: 1
time_ms: 250
memory_kb: 1160
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
using namespace std;

vector<int> adj_list[30];

// Check whether a set dset of size k is a dominating set of a graph
// of n vertices.
bool is_dominating_set(int dset, int n)
{
  bool dominated[30];
  int rem = n;                  // ??????????????????????????????????????°

  for (int i=0;i<n;i++) dominated[i]=false;
  for (int v=0;v<n;v++)
  {
    int vm = 1<<v;              // ??????v?????´??°??¨???
    int im;
    if (vm & dset)              // v???dset?????????
    {
      for (int i=0;i<adj_list[v].size();i++)
      {
        int w = adj_list[v][i];
        if (!dominated[w]) { dominated[w] = true; rem--; }
      }
    }
  }
  if (rem == 0) return true;
  else return false;
}

int main()
{
  int n, m;
  int u, v;
  while (cin >> n >> m)
  {
    bool found = false;

    if (n == 0) return 0;
    for (int i=0;i<n;i++) adj_list[i].clear();
    for (int i=0;i<n;i++) adj_list[i].push_back(i);
    for (int i=0;i<m;i++)
    {
      cin >> u >> v;
      adj_list[u].push_back(v);
      adj_list[v].push_back(u);
    }
    int Delta = 0;              // ?????§?¬???°
    for (int i=0;i<n;i++) Delta = max(Delta, (int)adj_list[i].size());

    int dset;
    for (int k=n/Delta;k<=n;k++)
    {
      // {0,...,n-1}?????¨???????????§????????????k??§???????????????????????????
      // ????????°???????????°????????????????????£??¬???????????????????????§
      dset = (1 << k) - 1;
      while (dset < 1<<n)
      {
        if (is_dominating_set(dset, n))
        {
          cout << k << endl;
          found = true;
        }
        if (found) break;

        int x = dset & -dset;
        int y = dset + x;
        dset = ((dset & ~y) / x >> 1) | y;
      }
      if (found) break;
    }
  }
}
accuracy: 1
time_ms: 470
memory_kb: 1216
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
using namespace std;

vector<int> adj_list[30];

// Check whether a set dset of size k is a dominating set of a graph
// of n vertices.
bool is_dominating_set(int dset, int n)
{
  bool dominated[30];
  int rem = n;                  // ??????????????????????????????????????°

  for (int i=0;i<30;i++) dominated[i]=false;
  for (int v=0;v<n;v++)
  {
    int vm = 1<<v;              // ??????v?????´??°??¨???
    int im;
    if (vm & dset)              // v???dset?????????
    {
      for (int i=0;i<adj_list[v].size();i++)
      {
        int w = adj_list[v][i];
        if (!dominated[w]) { dominated[w] = true; rem--; }
      }
    }
  }
  if (rem == 0) return true;
  else return false;
}

int main()
{
  int n, m;
  int u, v;
  while (cin >> n >> m)
  {
    bool found = false;

    if (n == 0) return 0;
    for (int i=0;i<n;i++) adj_list[i].clear();
    for (int i=0;i<n;i++) adj_list[i].push_back(i);
    for (int i=0;i<m;i++)
    {
      cin >> u >> v;
      adj_list[u].push_back(v);
      adj_list[v].push_back(u);
    }

    int dset;
    for (int k=1;k<=n;k++)
    {
      // {0,...,n-1}?????¨???????????§????????????k??§???????????????????????????
      // ????????°???????????°????????????????????£??¬???????????????????????§
      dset = (1 << k) - 1;
      while (dset < 1<<n)
      {
        if (is_dominating_set(dset, n))
        {
          cout << k << endl;
          found = true;
        }
        if (found) break;

        int x = dset & -dset;
        int y = dset + x;
        dset = ((dset & ~y) / x >> 1) | y;
      }
      if (found) break;
    }
  }
}
accuracy: 1
time_ms: 470
memory_kb: 1216
final_rank: 8

code_snippet: #include <iostream>
using namespace std;

bool matrix[30][30];

// Check whether a set dset of size k is a dominating set of a graph
// of n vertices.
bool is_dominating_set(int dset, int n)
{
  bool dominated[30];
  int rem = n;                  // ??????????????????????????????????????°

  for (int i=0;i<30;i++) dominated[i]=false;
  for (int v=0;v<n;v++)
  {
    int vm = 1<<v;              // ??????v?????´??°??¨???
    int im;
    if (vm & dset)              // v???dset?????????
    {
      if (!dominated[v]) { dominated[v] = true; rem--; }
      for (int i=0;i<n;i++)
        if (matrix[v][i] && !dominated[i]) { dominated[i] = true; rem--; }
    }
  }
  if (rem == 0) return true;
  else return false;
}


int main()
{
  int n, m;
  int u, v;
  while (cin >> n >> m)
  {
    bool found = false;

    if (n == 0) return 0;
    for (int i=0;i<n;i++) for (int j=0;j<n;j++) matrix[i][j]=false;
    for (int i=0;i<m;i++)
    {
      cin >> u >> v;
      matrix[u][v] = matrix[v][u] = true;
    }

    int dset;
    for (int k=1;k<=n;k++)
    {
      // {0,...,n-1}?????¨???????????§????????????k??§???????????????????????????
      // ????????°???????????°????????????????????£??¬???????????????????????§
      dset = (1 << k) - 1;
      while (dset < 1<<n)
      {
        if (is_dominating_set(dset, n))
        {
          cout << k << endl;
          found = true;
        }
        if (found) break;

        int x = dset & -dset;
        int y = dset + x;
        dset = ((dset & ~y) / x >> 1) | y;
      }
      if (found) break;
    }
  }
}
accuracy: 1
time_ms: 1430
memory_kb: 1160
final_rank: 12

code_snippet: #include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
vector<int>g[40];
int v[40];
int deg[40];
pair<int,int>pt[40];
int n;
int dfs(int a){
	if(a==n){
		return 0;
	}
	int ret=999999999;
	v[pt[a].second]=-1;
	bool ok=true;
	for(int i=0;i<=a;i++){
		int f=pt[i].second;
		if(~v[f])continue;
		bool OK=false;
		for(int j=0;j<g[f].size();j++)if(~v[g[f][j]]){OK=true;break;}
		if(!OK){ok=false;break;}
	}
	if(ok){
		ret=min(ret,dfs(a+1));
	}
	v[pt[a].second]=1;
	ret=min(ret,dfs(a+1)+1);
	v[pt[a].second]=0;
	return ret;
}
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		n=a;
		for(int i=0;i<a;i++)g[i].clear();
		for(int i=0;i<a;i++)v[i]=0;
		for(int i=0;i<b;i++){
			int p,q;scanf("%d%d",&p,&q);
			g[p].push_back(q);g[q].push_back(p);
			deg[p]++;deg[q]++;
		}
		int ret=0;
		for(int i=0;i<a;i++)pt[i]=make_pair(deg[i],i);
		ret=dfs(0);
		printf("%d\n",ret);
	}
}
accuracy: 1
time_ms: 4460
memory_kb: 1052
final_rank: 20

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

int b[30];
vector<vector<int> > G;

int dfs(int x,int u,int n){
  if(x<0)return n;
  int m=dfs(x-1,u|1<<x,n+1);
  bool f=false;
  for(auto e:G[x]){
    f|=!(b[e]&u)&&1<<x==(b[e]&-b[e]);
  }
  if(!f){
    m=min(m,dfs(x-1,u,n));
  }
  return m;
}

int main(){
  for(int x,y;cin>>x>>y,x|y;){
    G=vector<vector<int> >(x);
    for(int i=0;i<x;i++){
      b[i]=1<<i;
      G[i].push_back(i);
    }
    while(y--){
      int u,v;
      cin>>u>>v;
      b[u]|=1<<v;
      b[v]|=1<<u;
      G[v].push_back(u);
      G[u].push_back(v);
    }
    cout<<dfs(x-1,0,0)<<endl;
  }
}
accuracy: 1
time_ms: 680
memory_kb: 1216
final_rank: 10

code_snippet: #include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

constexpr int MAX_N = 30;

int ans;
int n, m;
int cover[30];
int used;
int ok;
vector<vector<int>> edges;

void dfs(int idx, int sum) {
	if(sum >= ans) return;
	if(used == ok) {
		ans = sum;
		return;
	}
	if(idx == n) return;

	dfs(idx + 1, sum);
	const int tmp = used;
	used |= cover[idx];
	dfs(idx + 1, sum + 1);
	used = tmp;
}

int solve() {
	used = 0;
	int cnt = 0;
	for(int i = 0; i < n; ++i) {
		if(edges[i].size() == 0) {
			used |= (1 << i);
			++cnt;
		}
		else if(edges[i].size() == 1) {
			const int neighbor = edges[i][0];
			if(used & (1 << neighbor)) continue;
			used |= cover[neighbor];
			++cnt;
		}
	}

	ok = (1 << n) - 1;
	ans = n - __builtin_popcount(used) + cnt;
	dfs(0, cnt);
	return ans;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	while(cin >> n >> m && n) {
		memset(cover, 0, sizeof(cover));
		for(int i = 0; i < n; ++i) {
			cover[i] = (1 << i);
		}

		edges.assign(n, vector<int>());
		for(int i = 0; i < m; ++i) {
			int a, b;
			cin >> a >> b;
			cover[a] |= (1 << b);
			cover[b] |= (1 << a);
			edges[a].emplace_back(b);
			edges[b].emplace_back(a);
		}

		cout << solve() << endl;
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 70
memory_kb: 1216
final_rank: 2

code_snippet: #include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

constexpr int MAX_N = 30;

int ans;
int n, m;
int cover[30];
int used;
vector<vector<int>> edges;

void dfs(int idx, int sum) {
	if(sum >= ans) return;
	if(used == (1 << n) - 1) {
		ans = sum;
		return;
	}
	if(idx == n) return;

	dfs(idx + 1, sum);
	const int tmp = used;
	used |= cover[idx];
	dfs(idx + 1, sum + 1);
	used = tmp;
}

int solve() {
	used = 0;
	int cnt = 0;
	for(int i = 0; i < n; ++i) {
		if(edges[i].size() == 0) {
			used |= (1 << i);
			++cnt;
		}
		else if(edges[i].size() == 1) {
			const int neighbor = edges[i][0];
			if(used & (1 << neighbor)) continue;
			used |= cover[neighbor];
			++cnt;
		}
	}

	ans = n - __builtin_popcount(used) + cnt;
	dfs(0, cnt);
	return ans;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	while(cin >> n >> m && n) {
		memset(cover, 0, sizeof(cover));
		for(int i = 0; i < n; ++i) {
			cover[i] = (1 << i);
		}

		edges.assign(n, vector<int>());
		for(int i = 0; i < m; ++i) {
			int a, b;
			cin >> a >> b;
			cover[a] |= (1 << b);
			cover[b] |= (1 << a);
			edges[a].emplace_back(b);
			edges[b].emplace_back(a);
		}

		cout << solve() << endl;
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 70
memory_kb: 1220
final_rank: 4

code_snippet: #include <algorithm>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;

constexpr int MAX_N = 30;

int ans;
int n, m;
int cover[30];
int used;
vector<vector<int>> edges;

void dfs(int idx, int sum) {
	if(sum >= ans) return;
	if(used == (1 << n) - 1) {
		ans = sum;
	}
	if(idx == n) return;

	dfs(idx + 1, sum);
	const int tmp = used;
	used |= cover[idx];
	dfs(idx + 1, sum + 1);
	used = tmp;
}

int solve() {
	used = 0;
	int cnt = 0;
	for(int i = 0; i < n; ++i) {
		if(edges[i].size() == 0) {
			used |= (1 << i);
			++cnt;
		}
		else if(!(used & (1 << i))) {
			for(int j = 0; j < static_cast<int>(edges[i].size()); ++j) {
				if(edges[edges[i][j]].size() == 1) {
					used |= cover[i];
					++cnt;
					break;
				}
			}
		}
	}

	ans = n - __builtin_popcount(used) + cnt;
	dfs(0, cnt);
	return ans;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	while(cin >> n >> m && n) {
		memset(cover, 0, sizeof(cover));
		for(int i = 0; i < n; ++i) {
			cover[i] = (1 << i);
		}

		edges.assign(n, vector<int>());
		for(int i = 0; i < m; ++i) {
			int a, b;
			cin >> a >> b;
			cover[a] |= (1 << b);
			cover[b] |= (1 << a);
			edges[a].emplace_back(b);
			edges[b].emplace_back(a);
		}

		cout << solve() << endl;
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 80
memory_kb: 1220
final_rank: 5

code_snippet: #include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;

#define dump(a) (cerr << (#a) << " = " << (a) << endl)

template<class T> inline void chmax(T& a, const T& b) { if(b > a) a = b; }
template<class T> inline void chmin(T& a, const T& b) { if(b < a) a = b; }

template<typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
	os << '(' << p.first << ", " << p.second << ')';
	return os;
}

template<class Tuple, unsigned Index>
void print_tuple(ostream& os, const Tuple& t) {}

template<class Tuple, unsigned Index, class Type, class... Types>
void print_tuple(ostream& os, const Tuple& t) {
	if(Index > 0) os << ", ";
	os << get<Index>(t);
	print_tuple<Tuple, Index + 1, Types...>(os, t);
}

template<class... Types>
ostream& operator<<(ostream& os, const tuple<Types...>& t) {
	os << '(';
	print_tuple<tuple<Types...>, 0, Types...>(os, t);
	return os << ')';
}

template<class Iterator>
ostream& dump_range(ostream&, Iterator, const Iterator&);

template<typename T>
ostream& operator<<(ostream& os, vector<T> c) {
	return dump_range(os, c.cbegin(), c.cend());
}

template<class Iterator>
ostream& dump_range(ostream& os, Iterator first, const Iterator& last) {
	os << '[';
	for(int i = 0; first != last; ++i, ++first) {
		if(i) os << ", ";
		os << *first;
	}
	return os << ']';
}

int ans;
int n, m;
vector<int> cover;
int used;
vector<vector<int>> edges;

void dfs(int idx, int sum) {
	if(sum >= ans) return;

	if(idx == n) {
		if(used == (1 << n) - 1) ans = sum;
	}
	else {
		dfs(idx + 1, sum);
		const int tmp = used;
		used |= cover[idx];
		dfs(idx + 1, sum + 1);
		used = tmp;
	}
}

int solve() {
	cover.assign(n, 0);
	for(int i = 0; i < n; ++i) {
		cover[i] |= (1 << i);
		for(int j = 0; j < static_cast<int>(edges[i].size()); ++j) {
			cover[i] |= (1 << edges[i][j]);
		}
	}

	used = 0;
	int cnt = 0;
	for(int i = 0; i < n; ++i) {
		if(edges[i].size() == 0) {
			used |= (1 << i);
			++cnt;
		}
		else if(!(used & (1 << i))) {
			for(int j = 0; j < static_cast<int>(edges[i].size()); ++j) {
				if(edges[edges[i][j]].size() == 1) {
					used |= cover[i];
					++cnt;
					break;
				}
			}
		}
	}

	ans = n - __builtin_popcount(used) + cnt;
	dfs(0, cnt);
	return ans;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	while(cin >> n >> m && n) {
		edges.assign(n, vector<int>());
		for(int i = 0; i < m; ++i) {
			int a, b;
			cin >> a >> b;
			edges[a].emplace_back(b);
			edges[b].emplace_back(a);
		}

		cout << solve() << endl;
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 70
memory_kb: 1216
final_rank: 2

code_snippet: #include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;

#define dump(a) (cerr << (#a) << " = " << (a) << endl)

template<class T> inline void chmax(T& a, const T& b) { if(b > a) a = b; }
template<class T> inline void chmin(T& a, const T& b) { if(b < a) a = b; }

template<typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
	os << '(' << p.first << ", " << p.second << ')';
	return os;
}

template<class Tuple, unsigned Index>
void print_tuple(ostream& os, const Tuple& t) {}

template<class Tuple, unsigned Index, class Type, class... Types>
void print_tuple(ostream& os, const Tuple& t) {
	if(Index > 0) os << ", ";
	os << get<Index>(t);
	print_tuple<Tuple, Index + 1, Types...>(os, t);
}

template<class... Types>
ostream& operator<<(ostream& os, const tuple<Types...>& t) {
	os << '(';
	print_tuple<tuple<Types...>, 0, Types...>(os, t);
	return os << ')';
}

template<class Iterator>
ostream& dump_range(ostream&, Iterator, const Iterator&);

template<typename T>
ostream& operator<<(ostream& os, vector<T> c) {
	return dump_range(os, c.cbegin(), c.cend());
}

template<class Iterator>
ostream& dump_range(ostream& os, Iterator first, const Iterator& last) {
	os << '[';
	for(int i = 0; first != last; ++i, ++first) {
		if(i) os << ", ";
		os << *first;
	}
	return os << ']';
}

int ans;
int n, m;
vector<int> cover;
int used;
vector<vector<int>> edges;

void update(int value) {
	if(used == (1 << n) - 1) {
		ans = value;
	}
}

void dfs(int idx, int sum) {
	if(sum >= ans) return;

	if(idx == n) {
		update(sum);
	}
	else {
		dfs(idx + 1, sum);

		int tmp = used;
		used |= cover[idx];
		dfs(idx + 1, sum + 1);
		swap(used, tmp);
	}
}

int solve() {
	cover.assign(n, 0);
	for(int i = 0; i < n; ++i) {
		cover[i] |= (1 << i);
		for(int j = 0; j < static_cast<int>(edges[i].size()); ++j) {
			cover[i] |= (1 << edges[i][j]);
		}
	}

	used = 0;
	int cnt = 0;
	for(int i = 0; i < n; ++i) {
		if(edges[i].size() == 0) {
			used |= (1 << i);
			++cnt;
		}
	}

	ans = n;
	dfs(0, cnt);
	return ans;
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	while(cin >> n >> m && n) {
		edges.assign(n, vector<int>());
		for(int i = 0; i < m; ++i) {
			int a, b;
			cin >> a >> b;
			edges[a].emplace_back(b);
			edges[b].emplace_back(a);
		}

		cout << solve() << endl;
	}

	return EXIT_SUCCESS;
}
accuracy: 1
time_ms: 180
memory_kb: 1212
final_rank: 7

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
typedef vector<int> Node;
typedef vector<Node> Graph;
int min_ans;
int N, M;
Graph G;
int dfs(int k, int cur, vector<bool> adj){
  if(min_ans <= cur) return INF;
  if(k == N){
    REP(i, N) if(!adj[i]) return INF;
    return min_ans = cur;
  }
  int res = INF;
  res = min(res, dfs(k + 1, cur, adj));
  REP(i, G[k].size()){
    int u = G[k][i];
    adj[u] = true;
  }
  adj[k] = true;
  res = min(res, dfs(k + 1, cur + 1, adj));
  return res;
}
int main(){
  while(cin >> N >> M && N){
    G = Graph(N);
    vector<int> perm(N);
    REP(i, N) perm[i] = i;
    random_shuffle(perm.begin(), perm.end());
    REP(i, M){
      int a, b;
      cin >> a >> b;
      a = perm[a];
      b = perm[b];
      G[a].push_back(b);
      G[b].push_back(a);
    }
    min_ans = INF;
    vector<bool> adj(N, false);
    cout << dfs(0, 0, adj) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 2480
memory_kb: 1236
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

const int WHITE = 1;
const int BLACK = 2;
const int MAXV = 31;
int V;
vector<int> E[MAXV];
int numD[MAXV];
int color[MAXV];
int ans;

bool isValid() {
  bool flag[MAXV];
  fill(flag, flag+V, false);
  for(int i = 0; i < V; ++i) {
    if(color[i] == BLACK) {
      flag[i] = true;
      for(int j = 0; j < E[i].size(); ++j) {
	flag[E[i][j]] = true;
      }
    }
  }
  for(int i = 0; i < V; ++i) {
    if(!flag[i]) return false;
  }
  return true;
}

void rec(int p, int c) {
  if(p == V) {
    if(isValid()) {
      ans = min(ans, c);
    }
    return;
  }
  if(c >= ans) return;
  color[p] = BLACK;
  rec(p+1, c+1);
  color[p] = WHITE;
  rec(p+1, c);
}

int main() {
  int x, y;
  while(cin >> x >> y && (x|y)) {
    for(int i = 0; i < MAXV; ++i) E[i].clear();
    V = x;
    int a, b;
    while(y--) {
      cin >> a >> b;
      E[a].push_back(b);
      E[b].push_back(a);
    }
    ans = V;
    fill(numD, numD+MAXV, 0);
    rec(0, 0);
    cout << ans <<  endl;
  }
  return 0;
}
accuracy: 1
time_ms: 770
memory_kb: 1216
final_rank: 11