问题描述
给定一个N个点M条边的无向图G(点的编号从1至N),问是否存在一个不超过K个点的集合S,使得G中的每条边都至少有一个点在集合S中。
输入格式 输入的第一行包含一个整数T,表示数据的组数。 接下来T组数据中:每组输入的第一行包含三个整数n, m,
k,分别表示图的点数,边数,集合点数的最大值。接下来m行,每行2个正整数x,y,表示编号为 x 的节点与编号为 y 的节点间有一条边相连。
输出格式
对于每组测试数据,若其存在解,则将解输出出来:第一行为一个整数t,表示所选点集的大小;第二行为t个整数,表示所选的点的编号。如果存在多组解,只要输出其中一种方案即可(会有special
judge程序对你的输出进行检查)。 若该组测试数据不包含解,则输出一个数-1(一行)。
样例输入
2
10 8 3
6 4
7 2
7 4
7 6
9 3
9 5
10 6
10 9
10 8 2
6 4
7 2
7 4
7 6
9 3
9 5
10 6
10 9
样例输出
3
6 7 9
-1
数据规模和约定 对于80%的数据,满足 0<n<=20, m<=200, k<=20。 所有的数据满足 0<n<=100,
m<=5000, k<=20。
根据边来递归,然后讨论两个点是否要选。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int N=105;
const int inf=0x3f3f3f3f;
int vis[N],n,m,k;
struct node{
int x,y;
}s[5005];
int dfs(int pos,int num){//分别为当前边的位置,选择点的个数
if(pos==m) return 1;
int x=s[pos].x,y=s[pos].y;
if(!vis[x]&&!vis[y]){//如果两个点都没有被选过,分情况讨论
if(num==k) return 0;
vis[x]=1;
if(dfs(pos+1,num+1)) return 1;
vis[x]=0;
vis[y]=1;
if(dfs(pos+1,num+1)) return 1;
vis[y]=0;
}
else if(dfs(pos+1,num)){
return 1;
}
return 0;
}
int main()
{
int i,T,x,y;
scanf("%d",&T);
while(T--){
scanf("%d %d %d",&n,&m,&k);
memset(vis,0,sizeof(vis));
for(i=0;i<m;i++){
scanf("%d %d",&s[i].x,&s[i].y);
}
if(dfs(0,0)){
int ans=0;
for(i=1;i<=n;i++){
if(vis[i]) ans++;
}
printf("%d\n",ans);
for(i=1;i<=n;i++){
if(vis[i]) printf("%d ",i);
}
}
else puts("-1");
printf("\n");
}
return 0;
}