题目地址:http://acm.scu.edu.cn/soj/problem.action?id=4439
题目意思:给定n个点m条边,给点染色,问如何染色可以是的每条边的端点至少有一个点被染色。求染色的最小值(染色最小的点满足条件)
题解:因为输入的时候保证。所以即使是最坏的情况的,前30个点都染色就也可以满足条件,因此,对前30个点的状态枚举dfs暴搜(得剪枝)一下就过了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <iostream>
#define N 505
using namespace std;
vector<int>v[N];
int n,m,tot,ans;
int vis[505];
void dfs(int s,int flag,int len)
{
int i,k;
if(len>=ans)
return;
if(s==tot)
{
ans=min(ans,len);
return;
}
if(s!=0)
{
if(flag==0)
{
k=v[s].size();
for(i=0;i<k;i++)
{
if(!vis[v[s][i]])
{
len++;
}
vis[v[s][i]]++;
}
}
}
if(vis[s+1])
dfs(s+1,1,len);
else
{
vis[s+1]++;
dfs(s+1,1,len+1);
vis[s+1]--;
dfs(s+1,0,len);
}
if(flag==0)
{
k=v[s].size();
for(i=0;i<k;i++)
{
if(!vis[v[s][i]])
{
len++;
}
vis[v[s][i]]--;
}
}
}
int main()
{
int i;
int s,t;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(vis,0,sizeof(vis));
ans=N;
tot=min(30,n);
for(i=1;i<=n;i++)
v[i].clear();
for(i=1;i<=m;i++)
{
scanf("%d%d",&s,&t);
v[s].push_back(t);
v[t].push_back(s);
}
dfs(0,0,0);
printf("%d\n",ans);
}
return 0;
}