C - Coolest Ski Route(关于DAG图的最长路问题四种解法)

本文详细介绍了三种解决图中寻找最长路径问题的算法:BFS(广度优先搜索)、SPFA(Shortest Path Faster Algorithm)以及动态规划的DFS+DP优化解法。通过实例代码展示了如何在有向图中找到从起点到终点的最长距离,并对比了不同算法的适用场景和效率。

VJ链接

C - Coolest Ski Routehttps://vjudge.net/contest/491449#problem/C

首先是比赛中用的bfs写法

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<set>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
typedef pair<int, int>PII;
int e[N], w[N], ne[N], cnt, h[N];
int dist[N];
int n, m;
int in[N], out[N];
void add(int a, int b, int c)
{
	e[cnt] = b, w[cnt] = c, ne[cnt] = h[a], h[a] = cnt++;
}
int  bfs(int s)
{
	memset(dist, 0, sizeof dist);
	queue<PII>q;
	dist[s] = 0;
	q.push({ 0,s });
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		int ver = t.second, dis = t.first;
		for (int i = h[ver]; i != -1; i = ne[i])
		{
			int j = e[i];
			if (dist[j] < dist[ver] + w[i])
			{
				dist[j] = dist[ver] + w[i];
				q.push({ dist[j],j });
			}
		}
	}
	int maxx = -INF;
	for (int i = 1; i <= n; i++)maxx = max(maxx, dist[i]);
	return maxx;
}
int main()
{
	memset(h, -1, sizeof h);
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
		in[b]++;
	}
	int ans = -INF;
	for (int i = 1; i <= n; i++)
	{
		if (in[i] == 0)
		{
			ans = max(bfs(i), ans);
		}
	}
	cout << ans << endl;
	return 0;
}

下面是spfa求最长路,spfa可以求DAG的最长路问题

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<set>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
typedef pair<int, int>PII;
int e[N], w[N], ne[N], cnt, h[N];
bool st[N];
int dist[N];
int n, m;
int in[N], out[N];
void add(int a, int b, int c)
{
	e[cnt] = b, w[cnt] = c, ne[cnt] = h[a], h[a] = cnt++;
}
int  spfa(int x)
{
	memset(st, false, sizeof st);
	memset(dist, 0, sizeof dist);
	dist[x] = 0;
	queue<int>q;
	q.push(x);
	st[x] = true;
	while (q.size())
	{
		auto t = q.front();
		q.pop();
		st[t] = false;
		for (int i = h[t]; i != -1; i = ne[i])
		{
			int j = e[i];
			if (dist[j] < dist[t] + w[i])
			{
				dist[j] = dist[t] + w[i];
				if (!st[j])q.push(j), st[j] = true;
			}
		}
	}
	int maxx = -INF;
	for (int i = 1; i <= n; i++)
	{
		maxx = max(dist[i], maxx);
	}
	return maxx;
}
int main()
{
	memset(h, -1, sizeof h);
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
		in[b]++;//统计入度
	}
	int ans = -INF;
	for (int i = 1; i <= n; i++)
	{
		if (in[i] == 0)//找到所有山顶,更新最大ans值
		{
			ans = max(spfa(i), ans);
		}
	}
	cout << ans << endl;
	return 0;
}

动态规划 dfs+dp优化解法,记忆搜索。dp值保存的是当前点到终点的最远距离

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
#include<set>
#include<unordered_map>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 10;
typedef pair<int, int>PII;
int e[N], w[N], ne[N], cnt, h[N];
int dist[N];
int n, m;
int in[N], out[N];
int dp[N];
void add(int a, int b, int c)
{
	e[cnt] = b, w[cnt] = c, ne[cnt] = h[a], h[a] = cnt++;
}
int  dfs(int s)
{
	if (dp[s])return dp[s];
	for (int i = h[s]; i != -1; i = ne[i])
	{
		int j = e[i];
		dp[s] = max(dp[s], dfs(j) + w[i]);
	}
	return dp[s];
}
int main()
{
	memset(h, -1, sizeof h);
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		add(a, b, c);
		in[b]++;
	}
	int ans = -INF;
	for (int i = 1; i <= n; i++)
	{
		if (in[i] == 0)
		{
			ans = max(dfs(i), ans);
		}
	}
	cout << ans << endl;
	return 0;
}

拓扑排序解法,该解法要统计每个点入度出度调一宿没调出来,先鸽了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值