#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
struct edge {
size_t finish;
int weight;
edge(size_t finish, int weight);
bool operator!=(const edge& other) {
return (finish != other.finish);
}
};
edge::edge(size_t fin, int weig)
: finish(fin), weight(weig)
{
//std::cout<<this->finish<< weight<<"jjj";
}
const static size_t kmax_size = 1000 * 1000 * 1000;
enum VertexStatus {
kundiscovered, kdiscovering, kprocecced
};
bool BFS(const std::vector<std::vector<edge>>& graph, std::vector<size_t>& ansestors, std::vector<size_t>& distance, std::vector<bool>& is_used, size_t start) {
std::queue<int> graph_queue;
graph_queue.push(start);
while (!graph_queue.empty()) {
size_t current_node = graph_queue.front();
is_used[current_node] = true;
graph_queue.pop();
for (auto iter : graph[current_node]) {
if (is_used[iter.finish]) {
if (distance[iter.finish] == distance[current_node]) {
return false;
}
}
if (!is_used[iter.finish]) {
ansestors[iter.finish] = current_node;
if (distance[iter.finish] == 5) {
distance[iter.finish] = 1 - distance[current_node];
}
if (distance[iter.finish] == distance[current_node]) {
return false;
}
is_used[iter.finish] = true;
graph_queue.push(iter.finish);
}
}
}
return true;
}
bool IsTwoPart(const std::vector<std::vector<edge>>& graph) {
std::vector<size_t> ansestors(graph.size(), kmax_size);
std::vector<size_t> part(graph.size(), 5);
std::vector<bool> is_used(graph.size(), false);
part[0] = 0;
for (size_t i = 0; i < graph.size(); ++i) {
if (!is_used[i]) {
part[i] = 0;
if (!BFS(graph, ansestors, part, is_used, i)) {
return false;
}
}
}
return true;
}
std::vector<size_t> DFS(const std::vector<std::vector<edge>>& graph, std::vector<VertexStatus>& nodes_colors, size_t start, size_t& result_e, std::vector<edge>& ansestors, std::vector<size_t>& cycle_vertecies, size_t ans, std::vector<int>& result, size_t& beg, int& shift, std::vector<edge>& path) {
nodes_colors[start] = kdiscovering;
//std::vector<size_t> path;
//std::cout<<start<<nodes_colors[start]<<graph[1][0] << nodes_colors[graph[1][0]] << "\n";
//std::cout << start << nodes_colors[start] << "\n";
for (auto vert : graph[start]) {
//std::cout << start << vert.finish << vert.weight<< "mmmm"<<"\n";
//for (auto it : ansestors) {
// std::cout << it << " ";
//}
// std::cout << "\n";
if (nodes_colors[vert.finish] == kdiscovering && vert.finish != ans) {
//std::cout << vert.finish << start << vert.weight << "vertstart" << "\n";// << " " << ansestors[start].finish << ansestors[ansestors[start].finish].finish << "\n";//<< ansestors[ansestors[ansestors[start]]]<< "ppp" << "\n";
if (path.size() == 0) {
auto iter = edge(start, vert.weight);
iter.finish = start;
int last_node;
iter.weight = 0;
for (; iter != vert; iter = ansestors[iter.finish]) {
//return 0;
//std::cout << iter.finish <<" "<< iter.weight<< " "<<ansestors[iter.finish].finish << "ffff"<< "\n";
path.push_back(iter);
if (iter.finish != vert.finish) {
last_node = iter.finish;
}
}
// return 0;
int tmp;
//std::cout<<last_node<<vert.finish<<"qqqqqq";
for (auto it : graph[last_node]) {
if (it.finish == vert.finish) {
tmp = it.weight;
}
}
vert.weight = tmp;
//std::cout<<vert.finish<<vert.weight<<start<<"\n";
path.push_back(vert);
//std::cout << "path_size" << path.size();
if (path.size() % 2 == 1) {
//std::cout << "yyyy" << "\n";
for (auto l : path) {
//std::cout << l.finish << l.weight<< " ";
}
//std::cout<< "hhhh"<< start<<"\n";
result[start] = 0;
beg = start;
//std::cout<< beg<<"mmuuumm";
//std::cout << start << path.size() << " iiiiiii" << "\n";
int temp;
for (auto iter : graph[start]) {
if (iter.finish == path[path.size() - 1].finish) {
temp = iter.weight;
}
}
//std::cout<<temp<<"wwww";
for (int i = 1;i < path.size();++i) {
result[path[i].finish] = path[i].weight - result[path[i - 1].finish] - 2;
//std::cout << path[i - 1].finish << path[i].finish << result[path[i].finish] << result[path[i - 1].finish] << path[i].weight << "uuuu"<<"\n";
}
//std::cout << path[2].finish<<path[2].weight<< "kkkk;";
//for (auto l :result) {
/// std::cout << l + 1 << " ";
// }
//std::cout << "\n";
shift = temp - 2 - result[start] - result[path[path.size() - 1].finish];
//std::cout <<start << shift <<"llll";
//std::cout << shift << start << result[start] << "aaaaa" << "\n";
ansestors[vert.finish] = edge(start, 0);
return {};
//result_e = vert;
//cycle_vertecies.push_back(vert);
//std::cout<< vert<<"vvvv";
return {};
}
}
if (path.size() % 2 == 0) {
path.clear();
}
}
if (nodes_colors[vert.finish] == kundiscovered) {
//std::cout << start << " " << vert.finish << vert.weight<< "\n";
ansestors[vert.finish] = edge(start, vert.weight);
ansestors[vert.finish].weight = vert.weight;
//std::cout << vert << nodes_colors[vert] << "\n";
DFS(graph, nodes_colors, vert.finish, result_e, ansestors, cycle_vertecies, start, result, beg, shift, path);
//return res;
}
}
nodes_colors[start] = kprocecced;
//cycle_vertecies.clear();
//for (auto it :ansestors) {
// std::cout << it << " ";
//// }
/// std::cout << "hhhh" << "\n";
return {};
}
void GetOddCycle(const std::vector<std::vector<edge>>& graph, std::vector<int>& result, size_t& start, int& shift) {
//std::vector<size_t> result;
std::vector<edge> path;
std::vector<size_t> cycle_vertecies;
std::vector<VertexStatus> nodes_colors(graph.size(), kundiscovered);
std::vector<edge> ansestors(graph.size(), edge(kmax_size, kmax_size));
std::vector<bool> is_used(graph.size(), false);
size_t result_e = kmax_size;
//for (size_t i = 0; i < graph.size(); ++i) {
// if (nodes_colors[i] == kundiscovered) {
//std::cout<< "uuuuu";
auto res = DFS(graph, nodes_colors, 0, result_e, ansestors, cycle_vertecies, kmax_size, result, start, shift, path);
//std::cout << start<< shift<< "rrrr";
return;
// }
//}
/*//std::cout<<result_e<<"uuuuu";
//size_t start;
if (result_e == kmax_size) {
return {};
}
std::vector<size_t> path_from_start_to_finish;
//for (auto it : ansestors) {
//std::cout<< it << " ";
// }
// std::cout << "\n";
for (auto res_e : cycle_vertecies) {
//std::cout << res_e << "\n";
for (auto iter = ansestors[res_e]; iter != res_e; iter = ansestors[iter]) {
path_from_start_to_finish.push_back(iter);
}
//std::cout<< path_from_start_to_finish.size() << "\n";
//for (auto it : path_from_start_to_finish) {
// std::cout << it << " ";
// }
return path_from_start_to_finish;
if (path_from_start_to_finish.size() % 2 == 0) {
path_from_start_to_finish.push_back(result_e);
std::reverse(path_from_start_to_finish.begin(), path_from_start_to_finish.end());
for (auto vert : path_from_start_to_finish) {
result.push_back(vert);
}
return {};
}
else {
path_from_start_to_finish.clear();
}
}
*/
//return;
}
void BFSOdd(const std::vector<std::vector<edge>>& graph, std::queue<int>& graph_queue, std::vector<bool>& is_used, size_t start, std::vector<int>& result, int& shift) {
//graph_queue.push(start);
//std::queue<int> ans_q;
//int shift;
//ans_q.push(kmax_size);
/* while (!graph_queue.empty()) {
size_t top = graph_queue.front();
int ans = ans_q.front();
ans_q.pop();
is_used[top] = true;
graph_queue.pop();
for (auto iter : graph[top]) {
if (!is_used[iter] && iter!=ans) {
result[iter] = edge_numbers[top][iter] - result[top];
ansestors[iter] = top;
distance[iter] = distance[top] + 1;
is_used[iter] = true;
graph_queue.push(iter);
ans_q.push(top);
std::cout << iter << result[iter] << "\n";
}
if (is_used[iter]) {
shift = edge_numbers[top][iter] - result[iter] - result[top];
std::cout<< top<< " " <<iter<<shift<<"\n";
break;
//for (int i = 0;i < result.size();++i) {
// result[i] = result[i] + (shift / 2);
// std::cout<<result[i];
// }
// std::cout<<"\n";
}
}
}
for (int i=0;i<is_used.size();++i) {
is_used[i]=false;
}*/
//std::cout<<shift<<start<<"gggg";
graph_queue.push(start);
result[start] += (shift / 2);
//std::cout<<start << shift << result[start] << "zzzzz";
for (auto k : result) {
//std::cout << k << " ";
}
//std::cout << "\n" << start << shift << "\n";
//std::cout <<"nnnn";
//std::cout << shift;
while (!graph_queue.empty()) {
size_t top = graph_queue.front();
//int ans = ans_q.front();
//ans_q.pop();
is_used[top] = true;
graph_queue.pop();
for (auto iter : graph[top]) {
if (!is_used[iter.finish]) {
result[iter.finish] = iter.weight - 2 - result[top];
//ansestors[iter] = top;
//distance[iter] = distance[top] + 1;
is_used[iter.finish] = true;
graph_queue.push(iter.finish);
//ans_q.push(top);
//std::cout << top << iter << result[iter] << "tttt"<< "\n";
}
}
}
for (auto l : result) {
std::cout << l + 1 << " ";
}
//std::cout<< "sssss"<<"\n";
}
std::vector<int> GetPath(const std::vector<std::vector<edge>>& graph) {
const size_t max_size = 1000 * 1000 * 1000;
int shift;
size_t start;
size_t gr_size = graph.size();
std::vector<int> result(gr_size, kmax_size);
std::queue<int> graph_queue;
GetOddCycle(graph, result, start, shift);
//std::cout<<start<<shift<<"\n";
//std::cout<< shift<<"bbbbb"<<"\n";
std::vector<size_t> ansestors(graph.size(), max_size);
//std::vector<size_t> distance(graph.size(), max_size);
std::vector<bool> is_used(graph.size(), false);
//distance[start] = 0;
//for (int vert = 0;vert < graph.size();++vert) {
/// if (!is_used[vert]) {
// result[vert] = 0;
//distance[vert] = 0;
BFSOdd(graph, graph_queue, is_used, start, result, shift);
// }
//}
/*if (is_used[finish]) {
//std::cout << distance[finish] << "\n";
std::vector<size_t> path_from_start_to_finish;
for (auto iter = finish; iter != start; iter = ansestors[iter]) {
path_from_start_to_finish.push_back(iter);
}
path_from_start_to_finish.push_back(start);
std::reverse(path_from_start_to_finish.begin(), path_from_start_to_finish.end());
for (auto iter = path_from_start_to_finish.begin(); iter != path_from_start_to_finish.end(); ++iter) {
result.push_back(*iter + 1);
}
}*/
return result;
}
std::vector<int> Even(const std::vector<std::vector<edge>>& graph) {
bool flag = true;
std::vector<int> result(graph.size(), kmax_size);
for (size_t i = 0;i < graph.size();++i) {
std::queue<int> graph_queue;
//std::vector<size_t> ansestors(graph.size(), kmax_size);
//std::vector<size_t> part(graph.size(), 5);
std::vector<bool> is_used(graph.size(), false);
graph_queue.push(i);
result[i] = 0;
while (!graph_queue.empty()) {
size_t current_node = graph_queue.front();
is_used[current_node] = true;
graph_queue.pop();
for (auto iter : graph[current_node]) {
if (is_used[iter.finish]) {
//std::cout << iter << current_node << result[iter] << result[current_node] << edge_numbers[current_node][iter] - 2 << "\n";
//if (distance[iter] == distance[current_node]) {
// return false;
//}
}
if (!is_used[iter.finish]) {
result[iter.finish] = iter.weight - 2 - result[current_node];
if (result[iter.finish] < 0) {
result.clear();
result.resize(graph.size());
flag = false;
continue;
}
graph_queue.push(iter.finish);
}
}
}
if (flag) {
break;
}
}
/* for (auto it : result) {
std::cout<<it<< " ";
}
std::cout<< "\n";
int max_val = kmax_size;
int index = 0;
for (int i = 0;i < result.size();++i) {
if (result[i] < max_val) {
max_val = result[i];
index = i;
}
}
//std::cout<<index<<max_val <<"\n";
std::queue<int> new_graph_queue;
std::queue<int> graph_queue_t;
for (int i = 0;i < is_used.size();++i) {
is_used[i] = false;
}
for (int i = 0;i < result.size();++i) {
result[i] = kmax_size;
}
//graph_queue.clear();
graph_queue_t.push(1);
result[1] = 0;
while (!graph_queue_t.empty()) {
size_t current_node = graph_queue_t.front();
is_used[current_node] = true;
graph_queue_t.pop();
for (auto iter : graph[current_node]) {
if (is_used[iter.finish]) {
//std::cout << iter << current_node << result[iter] << result[current_node] << edge_numbers[current_node][iter] - 2 << "\n";
//if (distance[iter] == distance[current_node]) {
// return false;
//}
}
if (!is_used[iter.finish]) {
result[iter.finish] = iter.weight - 2 - result[current_node];
graph_queue_t.push(iter.finish);
}
}
}
/* for (auto it : result) {
std::cout<<it<< " ";
}
std::cout<< "yyy" << "\n";
int max_val_s = kmax_size;
int index_s = 0;
for (int i = 0;i < result.size();++i) {
if (result[i] < max_val_s) {
max_val_s = result[i];
index_s = i;
}
}
//std::cout<< max_val_s<<index_s<<"\n";
std::vector<int> new_result(graph.size(), kmax_size);
std::vector<bool> new_is_used(graph.size(), false);
if (max_val_s <= max_val) {
new_result[index_s] = 0;
new_graph_queue.push(index_s);
}
else {
new_result[index] = 0;
new_graph_queue.push(index);
}
while (!new_graph_queue.empty()) {
size_t new_current_node = new_graph_queue.front();
new_is_used[new_current_node] = true;
new_graph_queue.pop();
for (auto new_iter : graph[new_current_node]) {
if (new_is_used[new_iter.finish]) {
//std::cout << iter << current_node << result[iter] << result[current_node] << edge_numbers[current_node][iter] - 2 << "\n";
//if (distance[iter] == distance[current_node]) {
// return false;
//}
}
if (!new_is_used[new_iter.finish]) {
new_result[new_iter.finish] = new_iter.weight - 2 - new_result[new_current_node];
new_graph_queue.push(new_iter.finish);
}
}
}
//std::cout<<index << "\n";*/
for (auto r : result) {
std::cout << r + 1 << " ";
}
return result;
}
int main() {
size_t node_q, temp, tmp;
int val;
size_t edge_q, start, finish;
std::cin >> node_q >> edge_q;
//std::vector<std::vector<size_t>> edge_numbers(node_q, std::vector<size_t>(node_q, 0));
std::vector<std::vector<edge>> graph(node_q);
for (int i = 0; i < edge_q; ++i) {
std::cin >> temp >> tmp >> val;
//std::cout<<"\n"<<val << "\n";
edge tede = edge(tmp - 1, val);
tede.weight = val;
//std::cout<<"kkkk"<<val<<" "<<tede.weight<<"\n";
graph[temp - 1].push_back(tede);
//std::cout<<"bbbb"<<tede.weight<<"\n";
edge tedge = edge(temp - 1, val);
tedge.weight = val;
graph[tmp - 1].push_back(tedge);
//edge_numbers[temp - 1][tmp - 1] = val;
//edge_numbers[tmp - 1][temp - 1] = val;
}
//std::cout << graph[0][0] << graph[0][1];
//std::cout << "jjjj";
std::vector<int> result(node_q, kmax_size);
if (IsTwoPart(graph)) {
//std::cout<< "pppp";
Even(graph);
}
else {
auto res = GetPath(graph);
}
/*if (res.size() == 0) {
std::cout << "NO";
}
else {
std::cout<<"YES" <<"\n";
std::vector<int> str = GetPath(graph, edge_numbers);
for (auto iter : str) {
std::cout << iter << " ";
}
}*/
return 0;
}