#include #include #include #include #include using namespace std; typedef vector > Graph; vector tsort(Graph G, int start, int end) { vector ret; int degree[end]; memset(degree, 0, sizeof(degree)); for (int from = start; from < end; from++) { for (int i = 0; i < G[from].size(); i++) { int to = G[from][i]; degree[to]++; } } stack root; for (int i = start; i < end; i++) { if (degree[i] == 0) { root.push(i); } } while (!root.empty()) { int from = root.top(); root.pop(); ret.push_back(from); for (int i = 0; i < G[from].size(); i++) { int to = G[from][i]; degree[to]--; if (degree[to] == 0) { root.push(to); } } } return ret; } struct Edge { int to; int cost; Edge(int to = -1, int cost = -1) { this->to = to; this->cost = cost; } }; int main() { int N, M; cin >> N >> M; Graph G(N); vector edges[N]; vector reverse_edges[N]; for (int i = 0; i < M; ++i) { int a, b, c; cin >> a >> b >> c; G[a].push_back(b); edges[a].push_back(Edge(b, c)); reverse_edges[b].push_back(Edge(a, c)); } vector res = tsort(G, 0, N); if (res.size() != N) { // tsort failed. cout << -1 << endl; } int dp[N]; memset(dp, 0, sizeof(dp)); int max_cost = 0; for (int i = 0; i < res.size(); ++i) { int v = res[i]; for (Edge &e : edges[v]) { int n_cost = dp[v] + e.cost; dp[e.to] = max(dp[e.to], n_cost); max_cost = max(max_cost, dp[e.to]); } } int min_cost[N]; for (int v = 0; v < N; ++v) { min_cost[v] = INT_MAX; } for (int i = N - 1; i >= 0; --i) { int v = res[i]; if (min_cost[v] == INT_MAX) { min_cost[v] = dp[v]; } for (Edge &e : reverse_edges[v]) { int b_cost = min_cost[v] - e.cost; min_cost[e.to] = min(min_cost[e.to], b_cost); } } int buf_size = 0; for (int v = 0; v < N; ++v) { // fprintf(stderr, "v: %d, dp: %d, min: %d\n", v, dp[v], min_cost[v]); if (dp[v] < min_cost[v]) ++buf_size; } cout << max_cost << " " << buf_size << "/" << N << endl; return 0; }