#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <climits>
using namespace std;
// 定义图的邻接表结构
vector<vector<pair<int, int>>> graph;
vector<int> dist; // 存储从起点到各点的最短距离
vector<vector<int>> prevNodes; // 存储最短路径的前驱节点
void dijkstra(int start, int n) {
// 初始化距离数组,初始值为无穷大
dist.assign(n + 1, INT_MAX);
// 初始化前驱节点数组
prevNodes.assign(n + 1, vector<int>());
// 使用优先队列(最小堆)来存储待处理的节点
// pair的第一个元素是距离,第二个元素是节点编号
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
// 起点到自己的距离为0
dist[start] = 0;
pq.push({0, start});
while (!pq.empty()) {
// 取出当前距离最小的节点
int currentDist = pq.top().first;
int u = pq.top().second;
pq.pop();
// 如果当前距离不是最短距离,跳过(因为可能已经更新过)
if (currentDist > dist[u]) continue;
// 遍历当前节点的所有邻居
for (auto& neighbor : graph[u]) {
int v = neighbor.first;
int weight = neighbor.second;
// 计算通过当前节点到达邻居的新距离
int newDist = dist[u] + weight;
// 如果找到更短的路径
if (newDist < dist[v]) {
dist[v] = newDist;
// 清空前驱节点,因为找到了更短的路径
prevNodes[v].clear();
prevNodes[v].push_back(u);
pq.push({newDist, v});
}
// 如果找到相同长度的路径,添加前驱节点
else if (newDist == dist[v]) {
prevNodes[v].push_back(u);
}
}
}
}
// 使用BFS收集所有可能的下一跳节点
void collectNextHops(int start, int end, vector<int> &nextHops) {
// 如果起点就是终点,没有下一跳
if (start == end) return;
// 使用队列进行BFS遍历
queue<int> q;
q.push(end);
// 使用集合记录已访问的节点,避免重复处理
vector<bool> visited(graph.size(), false);
visited[end] = true;
while (!q.empty()) {
int current = q.front();
q.pop();
// 遍历当前节点的所有前驱节点
for (int prev : prevNodes[current]) {
// 如果前驱节点是起点,那么当前节点就是可能的下一跳
if (prev == start) {
nextHops.push_back(current);
}
// 如果前驱节点未被访问,加入队列继续搜索
else if (!visited[prev]) {
visited[prev] = true;
q.push(prev);
}
}
}
}
int main() {
int N, K;
cin >> N >> K;
// 初始化图结构,大小为N+1(节点编号从1到N)
graph.resize(N + 1);
// 读取所有边信息并构建图
for (int i = 0; i < K; i++) {
int u, v, e;
cin >> u >> v >> e;
// 添加双向边(无向图)
graph[u].push_back({v, e});
graph[v].push_back({u, e});
}
int start, end;
cin >> start >> end;
// 特殊情况:起点和终点相同
if (start == end) {
cout << 0 << endl;
cout << -1 << endl;
return 0;
}
// 执行Dijkstra算法计算最短路径
dijkstra(start, N);
// 如果终点不可达
if (dist[end] == INT_MAX) {
cout << -1 << endl;
cout << -1 << endl;
return 0;
}
// 输出最低总能耗
cout << dist[end] << endl;
// 收集所有可能的下一跳节点
vector<int> nextHops;
collectNextHops(start, end, nextHops);
// 如果没有找到下一跳(理论上不应该发生,除非图结构有问题)
if (nextHops.empty()) {
cout << -1 << endl;
} else {
// 对下一跳节点进行排序
sort(nextHops.begin(), nextHops.end());
// 输出所有下一跳节点
for (int i = 0; i < nextHops.size(); i++) {
if (i > 0) cout << " ";
cout << nextHops[i];
}
cout << endl;
}
return 0;
}