通行证

通行证

题目大意

某俄罗斯贵族要在车上用闪光灯。
每条道路由若干个机构管辖,要在这条街道上使用闪光灯,至少要拥有其中一个机构的通行证。

找出一种方案,使得能通行与家与工作地点之间,且需要的通行证数最少。能,则输出要的通行证数和每个通行证的编号;否则,输出“impossible”
(家的编号为0,工作地点的编号为1)

输入样例

3 3 3
0 2 0
0 2 1
1 2 2

输出样例

2
0 2

数据范围

2 <= n <= 30
1 <= k <= 20

思路

这道题要用到dfs。
其实就是用dfs一波,同时要记得标记路程,就可以了。

代码

#include<cstdio>
#include<algorithm>
using namespace std;
struct note
{
	int l,j;
}g[31][31];
int k,n,m,a,b,c,number[31],answer[31],ans=2147483647;
bool in[31],f[31];
void dfs(int now,int an)//dfs
{
	if (an>=ans) return ;//距离已超过最小值,绝对不是最短
	if (now==1)//到达
	{
		if (an<ans)//路径更短
		{
			ans=0;
			for (int i=0;i<=k-1;i++)
			if (f[i])
			answer[++ans]=i;//标记
		}
		return ;
	}
	in[now]=1;//标记
	for (int i=1;i<=number[now];i++)
	if (!in[g[now][i].l])//判断是否到过
	if (f[g[now][i].j]) dfs(g[now][i].l,an);//dfs(通行证已有)
	else//还没有通行证
	{
		f[g[now][i].j]=1;//标记
		dfs(g[now][i].l,an+1);//dfs
		f[g[now][i].j]=0;//回溯
	}
	in[now]=0;//回溯
}
bool cmp(note x,note y)
{
	return x.j<y.j;
}
int main()
{
//	freopen("license.in","r",stdin);
//	freopen("license.out","w",stdout);
	scanf("%d%d%d",&k,&n,&m);//读入
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a,&b,&c);//读入
		g[a][++number[a]].l=b;//标记
		g[a][number[a]].j=c;
		g[b][++number[b]].l=a;
		g[b][number[b]].j=c;
	}
	for (int i=0;i<=n-1;i++)
	sort(g[i]+1,g[i]+number[i]+1,cmp);//排序
	dfs(0,0);//dfs
	if (ans!=2147483647)//判断是否能到达
	{
		printf("%d\n",ans);//输出
		for (int i=1;i<=ans;i++)
		printf("%d ",answer[i]);//输出
	}
	else printf("Impossible");//不能到达
//	fclose(stdin);
//	fclose(stdout);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值