给定一个正权有向无环图和图中的两个顶点,请编写程序找出这两个顶点间的最长路径,若两点间存在多条最长路径,则输出字典序最小者。假定图中包含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]);
}
}