描述
给出一个连通的有向图,求图中顶点 1 到顶点 n 的、经过其余顶点一次且仅一次的最短路径及其长度。
输入描述
第一行是两个整数 N(1≤N≤40),E(N<E<200),N 表示顶点个数,E 表示弧的数量。
接下来 E 行,每行是空格分隔的 3 个整数 u,v,l,分别表示从顶点 u 发出一条长度为 l 的弧到顶点 v 。1≤u,v≤N,0<l≤100
注意:可能存在重边。
输出描述
如果不存该路径,一行结果:No solution
否则,两行结果:第 1 行,该最短路的长度;第 2 行,从顶点 1 到顶点 n 的最短路,顶点之间用一个空格分隔,要求按路径的顶点次序,前一个顶点必须有弧指向后一个顶点。
用例输入 1
5 12 1 2 23 1 3 35 1 4 5 2 3 58 2 4 8 2 5 76 3 2 33 3 4 2 3 5 75 4 2 95 4 3 34 4 5 85
用例输出 1
140 1 2 4 3 5
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
int aim[45][2500];
int len[45][2500]; // 分别存储目标顶点编号和边长
int a_size[45]; // 记录每个顶点的邻接边数量
int q[45]; // 存储当前路径的顶点序列
int ww[45]; // 存储最短哈密顿路径的顶点序列
// 顶点数、边数、起点、终点、边的长度、当前最短路径的长度
int N, E, u, v, l, way;
bool book[45]; // 记录顶点是否被访问过的数组
// 深度优先搜索函数
void dfs(int i,int road,int num){
if(road>way)
return;
if(i==N&&num==N){
if(road<way){
way=road;
for(int j=0;j<N;++j)
ww[j]=q[j];
}
return;
}
for(int j=0;j<a_size[i];j++){
if (!book[aim[i][j]]){
book[aim[i][j]]=true;
road+=len[i][j];
q[num]=aim[i][j];
dfs(aim[i][j],road,num+1);
road-=len[i][j];
book[aim[i][j]]=false;
}
}
}
int main(){
cin>>N>>E;
for(int i=1;i<=E;i++){
cin>>u>>v>>l;
aim[u][a_size[u]++]=v;
len[u][a_size[u]-1]=l;
}
way=0x3f3f3f3f;
book[1]=true;
q[0]=1;
dfs(1,0,1);
if(way==0x3f3f3f3f){
cout<<"No solution"<<endl;
return 0;
}
cout<<way<<endl;
for(int i=0;i<N;i++)
cout<<ww[i]<< " ";
cout<<endl;
return 0;
}