#include <bits/stdc++.h>
using namespace std;
 
class Graph{ 
public: 
	int n;
	int m; 
	int maxEdges;
	bool isDirected;
 
	vector<vector<int>> adj;
	map<pair<int, int>, int> weightPairs;
 
	Graph(int nodes, bool isDiGraph) : adj(nodes){ 
		n = nodes;
		m = 0;
		isDirected = isDiGraph; 
		maxEdges = isDirected ? n*(n-1) : n*(n-1)/2;
	}
 
	void insertEdge(int u, int v, int weight){ 
 
		if(u >= n || v >=n || u < 0 || v < 0){ 
			cout<<"Either of the vertices doesn't exists in the graph.\n";
			return;
		}
 
		if(m == maxEdges){ 
			cout<<"Maximum allowed edges are already in the graph. Can't insert more.\n";
			return; 
		}
 
		weightPairs[{u, v}] = weight;
 
		adj[u].push_back(v); 
 
		++m; 
 
		if(!isDirected && u != v)
			adj[v].push_back(u);
	} 
 
	void deleteEdge(int u, int v){ 
 
		if(u >= n || v >=n || u < 0 || v < 0){
			cout<<"Either of the vertices doesn't exists in the graph.\n";
			return;
		}
 
		auto itr = find(adj[u].begin(), adj[u].end(), v);
 
		if(itr == adj[u].end()){ 
			cout<<"The edge doesn't exists in the graph.\n";
			return; 
		} 
 
		adj[u].erase(itr); --m;
 
		if(!isDirected && u != v){
			itr = find(adj[v].begin(), adj[v].end(), u);
			adj[v].erase(itr);
		}
	} 
 
	void displayGraph(){ 
 
		if(!m){ 
			cout<<"The graph is empty!!\n";
			return;
		} 
 
		cout<<"Total # edges in the graph: "<<m<<"\n";
 
		for(int i = 0; i < n; ++i){ 
			cout<<"The edges from vertex "<<i<<":";
 
			for(auto val: adj[i])  
				cout<<"->"<<val;
 
			cout<<"\n"; 
		}
		cout<<"=======================================================\n";
	}
 
	void singleSourceShortestPath(int src){
 
		/*================= Keys & predecessors initialization =================*/
		vector<int> shortestPaths(n, INT_MAX), predecessors(n, -1);
		/*================= Keys & predecessors initialization =================*/
		
		shortestPaths[src] = 0;
		
		int u, v;
		
		for(int i=1; i<n; ++i){
			
			for(auto &edge: weightPairs){
				
				u = edge.first.first, v = edge.first.second;
				
				int distUtoV = edge.second;
					
				if(shortestPaths[u] != INT_MAX && shortestPaths[u] + distUtoV < shortestPaths[v]){
					predecessors[v] = u;
					shortestPaths[v] = shortestPaths[u] + distUtoV;
				}
			}
			
		}
		
		bool flag = true;
			
		for(auto &edge: weightPairs){
				
			u = edge.first.first, v = edge.first.second;
				
			int distUtoV = edge.second;
			
			if(shortestPaths[u] != INT_MAX && shortestPaths[u] + distUtoV < shortestPaths[v]){
				cout<<"Graph contains negative cycles.\n"
				"No shortest path exits from given source to other nodes.\n";
				flag = false;
				break;
			}
		}
		
		if(flag){
			cout<<"The shortest paths from given source are,\n";
	 
			for(int u = 0; u < n; ++u){
				if(u != src){
					cout<<"----------------------------------------\n";
					if(shortestPaths[u] < INT_MAX){
						cout<<"Path length: "<<shortestPaths[u]<<" | Path: ";
						printPath(predecessors, u);
						cout<<"\n";
					}
					else{
						cout<<"No path exits from given source "<<src<<" to "<<u<<"\n";
					}
				}
			}
		}
	}
 
	void printPath(vector<int> &predecessors, int &par){
		if(par == -1)
			return;
 
		printPath(predecessors, predecessors[par]);
 
		cout<<(predecessors[par] == -1 ? "":"->")<<par;
	}
};
 
int main() {
	// your code goes here
	int n, u, v, w; 
	cin>>n;
 
	Graph g(n, 1);
 
	cin>>n;
 
	for(int i=0; i < n; ++i){
		cin>>u>>v>>w;
		g.insertEdge(u,v,w);
	}
 
	g.displayGraph();
 
	cin>>u;
	cout<<"Enter the source vertex for single source shortest path\n"
	"using Bellman-Ford algorithm: "<<u<<"\n";
	cout<<"------------------------------------------------------\n";
 
	g.singleSourceShortestPath(u);
 
	return 0;
}
