题目链接:http://acm.scu.edu.cn/soj/problem.action?id=4439
题意:n个点,m条边的无向图,n<=500,m<=n*(n-1)/2,对于每条边(u,v),min(u,v)<=30。求最少需要多少个点覆盖所有的边
解题思路:这题的关键点在于min(u,v)<=30。暴搜+剪枝。可以先选一个点,然后搜其他的点,回溯回来后,不选这个点,和它相邻的点都选
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
int n,m,ans,tot;
int visit[550];
int p,v;
vector<int>g[550];
void dfs(int k,int sum)
{
if(sum>ans) return;
if(k>tot)
{
ans=sum;
return ;
}
if(visit[k]) dfs(k+1,sum);
else
{
visit[k]++;
dfs(k+1,sum+1);
visit[k]--;
int Size=g[k].size();
for(int p=0;p<Size;p++)
{
v=g[k][p] ;
if(!visit[v]) sum++;
visit[v]++;
}
dfs(k+1,sum);
for(int p=0;p<Size;p++)
{
v=g[k][p];
visit[v]--;
if(!visit[v]) sum--;
}
}
}
int main()
{
int u, v ;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++) visit[i]=0,g[i].clear();
ans=INF;
tot=min(n,30);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
printf("%d\n",ans);
}
return 0 ;
}