7-9 最长路径 (10 分)

给定一个正权有向无环图和图中的两个顶点,请编写程序找出这两个顶点间的最长路径,若两点间存在多条最长路径,则输出字典序最小者。假定图中包含n个顶点,编号为0至n-1。

注:字典序,即对象在字典中的顺序。对于两个数字序列,从第一个数字开始比较,当某一个位置的数字不同时,该位置数字较小的序列,字典序较小,例如1 2 3 9比1 2 4 5小,1 2 8 9比1 2 10 3小。

输入格式:
输入第一行为3个正整数n和e,分别为图的顶点数和边数,均不超过50。接下来e行表示每条边的信息,每行为3个整数a、b、c,其中a和b表示该边的端点编号,c表示权值。各边并非按端点编号顺序排列。接下来1行为两个整数s和t,表示两个顶点编号。

输出格式:
输出顶点s到顶点t的字典序最小最长路径,路径中顶点编号用“->”间隔。如s和t不连通,则输出“none”。

输入样例:

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

结尾无空行
输出样例:

0->3->2

结尾无空行

知识点:

  • dfs深度优先搜索,回溯,剪枝

思路:

  • 本题是要求的最长路径,即s到t权值最大,深度遍历创建邻接表,vector<int > v[101]
  • dfs(int x,int y,int step,int sum),(x:当前节点,y目的节点,step:当前遍历步数,sum:从开始节点到当前节点的权值和,)
  • dfs函数步骤:
  • 1,出口当x==y是判断当前sum与maxsum的大小,然后保存遍历过的节点。
  • 2.遍历节点,从当前节点开始遍历他的邻接节点,然后用book[]标记遍历过的节点然后继续寻找记得进行回溯来寻找最长路径。

源码:

#include<bits/stdc++.h>
using namespace std;
int n, e;
int x, y;
vector<int> v[1005];
int book[1005];
int maxstep = -1;
int path[1005];
int temp[1005];
int w[1005][1005];
int maxsum = -1;
int flag = -1;
void dfs(int x, int y, int step, int sum) {
	if (x == y) {
		flag = 0;
		if (sum > maxsum) {
			maxsum = sum;
			maxstep = step;
			for (int i = 1;i < step;i++) {
				path[i] = temp[i];
			}
		}
		return;
	}
	int len = v[x].size();
	for (int i = 0;i < len;i++) {
		if (book[v[x][i]] == 0) {
			book[v[x][i]] = 1;
			temp[step] = v[x][i];
			dfs(v[x][i], y, step + 1, sum + w[x][v[x][i]]);
			temp[step] = 0;
			book[v[x][i]] = 0;
		}
	}
}
int main() {
	cin >> n >> e;
	for (int i = 0;i < e;i++) {
		int a, b, c;
		cin >> a >> b >> c;
		w[a][b] = c;
		v[a].push_back(b);
	}
	for (int i = 0;i < n;i++)
		sort(v[i].begin(), v[i].end());
	cin >> x >> y;
	path[0] = x;
	book[x] = 1;
	dfs(x, y, 1, 0);
	if (flag == -1) {
		cout << "none" << endl;;
		return 0;
	}
	for (int i = 0;i < maxstep;i++) {
		if (i == maxstep - 1)
			printf("%d", path[i]);
		else
			printf("%d->", path[i]);
	}

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 最长路径算法主要有两种实现方式:动态规划和拓扑排序。 1. 动态规划 动态规划是一种自底向上的算法,可以求解从一个起点到另一个终点的最长路径。具体实现步骤如下: 1)定义状态:用数组或矩阵表示每个节点的最长路径。 2)状态转移方程:对于每个节点,需要计算其能够到达的所有节点的最长路径,并选择其最大的作为该节点的最长路径。 3)最终结果:最长路径是所有节点的最大值。 Java 代码实现: ``` public class LongestPath { public int longestPath(int[][] graph, int start, int end) { int n = graph.length; int[] dp = new int[n]; Arrays.fill(dp, Integer.MIN_VALUE); dp[start] = 0; for (int i = start; i <= end; i++) { for (int j = 0; j < n; j++) { if (graph[i][j] != 0) { dp[j] = Math.max(dp[j], dp[i] + graph[i][j]); } } } return dp[end]; } } ``` 2. 拓扑排序 拓扑排序是一种基于有向无环图(DAG)的算法,可以求解从一个起点到另一个终点的最长路径。具体实现步骤如下: 1)构建拓扑排序序列:对于 DAG 的每个节点,按照其入度从小到大排序,得到一个拓扑排序序列。 2)计算最长路径:从起点开始,依次遍历拓扑排序序列的每个节点,更新其能够到达的所有节点的最长路径,并选择其最大的作为该节点的最长路径。 3)最终结果:最长路径是终点的最长路径。 Java 代码实现: ``` public class LongestPath { public int longestPath(int[][] graph, int start, int end) { int n = graph.length; int[] inDegree = new int[n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (graph[i][j] != 0) { inDegree[j]++; } } } Queue<Integer> queue = new LinkedList<>(); queue.offer(start); int[] dp = new int[n]; Arrays.fill(dp, Integer.MIN_VALUE); dp[start] = 0; while (!queue.isEmpty()) { int node = queue.poll(); for (int i = 0; i < n; i++) { if (graph[node][i] != 0) { inDegree[i]--; dp[i] = Math.max(dp[i], dp[node] + graph[node][i]); if (inDegree[i] == 0) { queue.offer(i); } } } } return dp[end]; } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值