#include <iostream>
#include <fstream>
#include <vector>
#include <deque>
#include <stack>
#include <tuple>
#include <queue>
#include <list>
#include <algorithm>
using namespace std;
class Graph {
struct nodeStruct {
int node1, node2, cost;
bool operator()(nodeStruct const& n1, nodeStruct const& n2) { return n1.cost > n2.cost; }
};
vector<list<nodeStruct>> adjacent;
vector<list<nodeStruct>> transposed();
void dfs(int ¤t, vector<bool>&visited, stack<int> &order);
void bfs(int &start, vector<int> &costs, vector<bool> &visited, deque<int> &queue, int &diameter);
void _biconnected(int &node, int parent, vector<bool> &visited, vector<int> &level, vector<int> &minLevel, stack<int> &s, vector<vector<int>> &components, vector<pair<int,int>> &criticalEdges);
void _hardConnected(int &node, vector<bool> &visited, vector<vector<int>> &components, vector<list<nodeStruct>> &t);
int findParent(int node, vector<int> &parent);
void _union(vector<int> &parents, vector<int> &height, const int &parent1, const int &parent2);
bool _hasPath(int ¤t, int &target, vector<bool> &visited);
public:
Graph(vector<tuple<int, int, int>> &data, int &nrNodes, bool oriented);
Graph(int &nrNodes) { adjacent.resize(nrNodes); }
friend ostream& operator<< (ostream& os, Graph graph) {
os << graph.adjacent.size() << " nodes\n";
for(int i = 0; i < graph.adjacent.size(); i++) {
os << "node " << i + 1 << ": ";
for(nodeStruct j: graph.adjacent[i])
os << "(" << j.node2 + 1 << ", " << j.cost << ") ";
os << "\n";
}
return os;
}
int connected();
pair<vector<int>, vector<bool>> costs(int start);
stack<int> topologicalSort();
pair<vector<vector<int>>, vector<pair<int,int>>> biconnected();
vector<vector<int>> hardConnected();
vector<int> dijkstra(int start);
pair<vector<int>, bool> bellmanFord(int start);
pair<vector<nodeStruct>, int> minimumTreeKruskall();
bool havelHakimi(deque<int> degrees);
int diameter();
void insertEdge(int node1, int node2, int cost, bool oriented = true);
bool hasPath(int current, int target);
};
int main() {
ifstream in("dijkstra.in");
ofstream out("dijkstra.out");
vector<tuple<int, int, int>> data;
int nrNodes, nrEdges;
in >> nrNodes >> nrEdges;
for(int i = 0; i < nrEdges; i++) {
int aux1, aux2, cost;
in >> aux1 >> aux2 >> cost;
data.emplace_back(aux1 - 1, aux2 - 1, cost);
}
Graph g(data, nrNodes, true);
auto dijks = g.dijkstra(0);
for(int i = 1; i < dijks.size(); i++) {
if(dijks[i] == -1)
out << "0 ";
else
out << dijks[i] << " ";
}
return 0;
}
Graph :: Graph(vector<tuple<int, int, int>> &data, int &nrNodes, bool oriented) {
adjacent.resize(nrNodes);
for(auto[node1, node2, cost]: data) {
adjacent[node1].push_back(nodeStruct({node1, node2, cost}));
if(!oriented)
adjacent[node2].push_back(nodeStruct({node2, node1, cost}));
}
}
vector<list<Graph :: nodeStruct>> Graph :: transposed() {
vector<list<nodeStruct>> ret(adjacent.size());
for(int i = 0; i < adjacent.size(); i++)
for(nodeStruct node: adjacent[i])
ret[node.node2].push_back(nodeStruct({i, node.cost}));
return ret;
}
void Graph :: dfs(int ¤t, vector<bool>&visited, stack<int> &order) {
visited[current] = true;
for(auto i: adjacent[current])
if(!visited[i.node2])
dfs(i.node2, visited, order);
order.push(current);
}
void Graph :: bfs(int &start, vector<int> &costs, vector<bool> &visited, deque<int> &queue, int &diameter) {
queue.push_back(start);
visited[start] = true;
costs[start] = 0;
while(queue.empty() != 1) {
const int current = queue.front();
for(auto i: adjacent[current])
if(!visited[i.node2]) {
costs[i.node2] += (costs[current] + 1);
diameter = costs[i.node2];
visited[i.node2] = true;
start = i.node2;
queue.push_back(i.node2);
}
queue.pop_front();
}
}
void Graph :: _biconnected(int &node, int parent, vector<bool> &visited, vector<int> &level, vector<int> &minLevel, stack<int> &s, vector<vector<int>> &components, vector<pair<int,int>> &criticalEdges) {
visited[node] = true;
minLevel[node] = level[node] = level[parent] + 1;
s.push(node);
for (auto x: adjacent[node])
if (x.node2 != parent) {
if (visited[x.node2])
minLevel[node] = min(minLevel[node], level[x.node2]);
else {
_biconnected(x.node2, node, visited, level, minLevel, s, components, criticalEdges);
minLevel[node] = min(minLevel[node], minLevel[x.node2]);
if(level[node] < minLevel[x.node2])
criticalEdges.emplace_back(node, x.node2);
if (minLevel[x.node2] >= level[node]) {
components.resize(components.size()+1);
while (s.top() != x.node2) {
components[components.size()-1].push_back(s.top());
s.pop();
}
components[components.size()-1].push_back(x.node2);
s.pop();
components[components.size()-1].push_back(node);
}
}
}
}
void Graph :: _hardConnected(int &node, vector<bool> &visited, vector<vector<int>> &components, vector<list<nodeStruct>> &t) {
visited[node] = false;
components[components.size() - 1].push_back(node);
for(auto j: t[node])
if(visited[j.node2])
_hardConnected(j.node2, visited, components, t);
}
int Graph :: findParent(int node, vector<int> &parent) {
while(parent[node] != 0)
node = parent[node];
return node;
}
void Graph :: _union(vector<int> &parents, vector<int> &height, const int &parent1, const int &parent2){
if(height[parent1] > height[parent2])
parents[parent2] = parent1;
else {
parents[parent1] = parent2;
if(height[parent1] == height[parent2])
height[parent2]++;
}
}
bool Graph :: _hasPath(int ¤t, int &target, vector<bool> &visited) {
if(visited[current])
return false;
visited[current] = true;
if(current == target)
return true;
for(auto i: adjacent[current])
if(_hasPath(i.node2, target, visited))
return true;
return false;
}
int Graph :: connected() {
vector<bool> visited(adjacent.size());
int nr = 0;
for(int i = 0; i < adjacent.size(); i++)
if(!visited[i]) {
stack<int> _;
nr++;
dfs(i, visited, _);
}
return nr;
}
pair<vector<int>, vector<bool>> Graph :: costs(int start) {
vector<int> costs(adjacent.size());
vector<bool> visited(adjacent.size());
deque<int> queue;
int _;
bfs(start, costs, visited, queue, _);
return make_pair(costs, visited);
}
stack<int> Graph :: topologicalSort() {
vector<bool> visited(adjacent.size());
stack<int> order;
for(int i = 0; i < adjacent.size(); i++)
if(!visited[i])
dfs(i, visited, order);
return order;
}
pair<vector<vector<int>>, vector<pair<int,int>>> Graph :: biconnected(){
stack<int> s;
vector<int> level(adjacent.size()), minLevel(adjacent.size());
vector<bool> visited(adjacent.size());
vector<vector<int>> components;
vector<pair<int,int>> criticalEdges;
for (int i = 0; i < adjacent.size(); i++)
if (visited[i] == 0)
_biconnected(i, 0, visited, level, minLevel, s, components, criticalEdges);
return make_pair(components, criticalEdges);
}
vector<vector<int>> Graph :: hardConnected() {
stack<int> s;
vector<bool> visited(adjacent.size());
vector<vector<int>> components;
vector<list<nodeStruct>> t = transposed();
for(int i = 0; i < adjacent.size(); i++)
if(!visited[i])
dfs(i, visited, s);
while(!s.empty()){
if(visited[s.top()]){
components.resize(components.size() + 1);
_hardConnected(s.top(), visited, components, t);
}
s.pop();
}
return components;
}
vector<int> Graph :: dijkstra(int start) {
vector<int> visited(adjacent.size()), distance(adjacent.size(), -1);
priority_queue<nodeStruct, vector<nodeStruct>, nodeStruct> costs;
costs.push({start, 0});
distance[start] = 0;
while(costs.empty() != 1) {
int node = costs.top().node1;
costs.pop();
if(!visited[node])
for(auto i: adjacent[node]){
if(!visited[i.node1])
if(distance[i.node1] == -1 || distance[i.node1] > i.cost + distance[node]){
distance[i.node1] = i.cost + distance[node];
costs.push({i.node1, distance[i.node1]});
}
}
visited[node] = 1;
}
return distance;
}
pair<vector<int>, bool> Graph :: bellmanFord(int start) {
const int inf = 250001;
vector<int> visited(adjacent.size()), distance(adjacent.size(), inf);
priority_queue<nodeStruct, vector<nodeStruct>, nodeStruct> costs;
costs.push({start, 0});
distance[start] = 0;
while(costs.empty() != 1) {
int node = costs.top().node2;
costs.pop();
for(auto i: adjacent[node]){
if(distance[i.node2] == inf || distance[i.node2] > i.cost + distance[node]){
distance[i.node2] = i.cost + distance[node];
costs.push({i.node2, distance[i.node2]});
visited[node]++;
if(visited[i.node2] >= adjacent.size())
return make_pair(distance, 1);
}
}
visited[node]++;
}
return make_pair(distance, 0);
}
pair<vector<Graph :: nodeStruct>, int> Graph :: minimumTreeKruskall() {
vector<int> parents(adjacent.size()), height(adjacent.size());
vector<nodeStruct> minimumSearchTree, sortedEdges;
int cost = 0, nrEdges = 0;
for(int i = 0; i < adjacent.size(); i++)
for(auto j: adjacent[i])
sortedEdges.push_back(j);
sort(sortedEdges.begin(), sortedEdges.end(), nodeStruct());
for(int i = sortedEdges.size() - 1; 0 <= i; i--){
const nodeStruct node = sortedEdges[i];
const int parent1 = findParent(node.node1, parents);
const int parent2 = findParent(node.node2, parents);
if(parent1 != parent2) {
cost += node.cost;
nrEdges++;
minimumSearchTree.push_back(node);
_union(parents, height, parent1, parent2);
if(nrEdges == adjacent.size() - 1)
return make_pair(minimumSearchTree, cost);
}
}
return make_pair(minimumSearchTree, cost);
}
int Graph :: diameter() {
vector<int> costs(adjacent.size());
vector<bool> visited(adjacent.size());
deque<int> queue;
int current = 0, diameter;
bfs(current, costs, visited, queue, diameter);
fill(costs.begin(), costs.end(), 0);
fill(visited.begin(), visited.end(), 0);
bfs(current, costs, visited, queue, diameter);
return diameter;
}
void Graph :: insertEdge(int node1, int node2, int cost, bool oriented) {
adjacent[node1].emplace_back(nodeStruct{node1, node2, cost});
if(!oriented)
adjacent[node2].emplace_back(nodeStruct{node2, node1, cost});
}
bool Graph :: hasPath(int current, int target) {
vector<bool> visited(adjacent.size());
return _hasPath(current, target, visited);
}
bool Graph :: havelHakimi(deque<int> degrees) {
int sum = 0;
for(auto i: degrees) {
sum += i;
if(i >= degrees.size())
return 0;
}
if(sum % 2)
return 0;
int nrNodes = degrees.size();
while(1) {
sort(degrees.begin(), degrees.end(),greater<>());
if(degrees[0] == 0)
return 1;
const int currentDegree = degrees[0];
degrees.pop_front();
for(int i = 0; i < degrees.size(); i++) {
degrees[i]--;
if(degrees[i] < 0)
return 0;
}
}
}