GPLT L2-038 病毒溯源

题面

病毒溯源

思路

该题目抽象出来是:“有一个图,你需要找到最长路径,如果有多条最长路径,输出字典序最小的一条。题目保证没有回路。”
做法:

  • 用领接表存储图
  • 用dfs遍历图,找到最长字典序最小的路径

实现

#include <iostream>
#include <cstring>

using namespace std;

const int N = 1e4 + 10;
int h[N], e[N], ne[N], ans[N], temp[N], idx, cnt, n;
bool st[N];

bool cmp()//长度相同情况下,判断答案是否最小
{
	for(int i = 0; i <= cnt; i ++)
		if(ans[i] != temp[i])
		{
			if(ans[i] > temp[i]) return true;
			else return false;
		}

	return false;
}

void dfs(int u, int l)
{
	temp[l] = u, st[u] = true;//放置第l个元素,如果不进行记忆化搜索,会被第五个测试点卡掉
	if(h[u] == -1)//表明这条路走到头了
	{
		if(l > cnt || (l == cnt && cmp()) )
		{
			memcpy(ans, temp, sizeof(int) * (l + 1));
			cnt = l;
		}
		return;
	}

	for(int i = h[u]; ~i; i = ne[i])
	{
		int j = e[i];
		dfs(j, l + 1);
	}
}

void add(int a, int b)
{
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

int main()
{
	memset(h, -1, sizeof h);

	cin >> n;
	for(int i = 0; i < n; i ++)
	{
		int k;
		cin >> k;
		for(int j = 1; j <= k; j ++)
		{
			int t;
			cin >> t;
			add(i, t);
		}
	}

	for(int i = 0; i < n; i ++)
		if(!st[i]) dfs(i, 0);//如果该点遍历过,说明前面从某个点起的路径,比从当前点起的路径长

	cout << cnt + 1 << endl;
	for(int i = 0; i <= cnt; i ++) cout << ans[i] << " \n"[i == cnt];

	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值