试题 算法提高 vertex cover

试题 算法提高 vertex cover

资源限制
时间限制:2.0s 内存限制:256.0MB
问题描述
  给定一个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<iostream>
#include<vector>
#include<cstring>
using namespace std;

struct Node{
	int x,y;

}a[5005];

int n,m,k;
int vis[105];
vector<int> q; 
bool dfs(int cur,int use)  //当前的编号,使用节点个数 
{
	if(cur == m)
	{
		return 1;
	} 
//	这条边的两个点都没选中 
	if(!vis[a[cur].x] && !vis[a[cur].y])
	{
		if(use == k)
		{
			return 0;
		} 
		vis[a[cur].x] = 1;//现任意选中一个点 
		if(dfs(cur+1,use+1))  //继续找下一层 
		{
			return 1;
		}
		vis[a[cur].x] = 0;//回归现场 
		
		vis[a[cur].y] = 1; 
		if(dfs(cur+1,use+1))
		{
			return 1;
		}
		vis[a[cur].y] = 0;
	}
	else if(dfs(cur+1,use)) //该边的某个端点已经被选中 
	{
		return 1;
	}
	
	return 0;
}
int main(void)
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(vis,0,sizeof(vis));
		cin>>n>>m>>k;
		for(int i = 0;i < m;i++)
		{
			cin>>a[i].x>>a[i].y;
		}
		
		if(dfs(0,0))
		{
			for(int i = 1;i <= n;i++)
			{
				if(vis[i])
				{
					q.push_back(i);
				}
			}
			cout<<q.size()<<endl;
			for(int i = 0;i < q.size();i++)
			{
				cout<<q[i]<<" ";
			}
			cout<<endl;
		}
		else
		{
			cout<<-1<<endl;
		}
		
	}
	
	return 0;
}
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值