#include #include #include #include using namespace std; using ll = long long; struct Edge { int from; int to; ll cost; }; using Graph = vector >; // トポロジカルソート vector topological_sort(const Graph& G) { int N = G.size(); vector indegree(N, 0); for (int u = 0; u < N; ++u) { for (const auto& e : G[u]) { indegree[e.to]++; } } queue q; for (int i = 0; i < N; ++i) { if (indegree[i] == 0) q.push(i); } vector order; while (!q.empty()) { int u = q.front(); q.pop(); order.push_back(u); for (const auto& e : G[u]) { if (--indegree[e.to] == 0) { q.push(e.to); } } } if ((int)order.size() != N) { throw runtime_error("Graph is not a DAG."); } return order; } // 最早開始時刻(EST) vector calc_EST(const vector& order, const Graph& G) { int N = G.size(); vector EST(N, 0); for (int u : order) { for (const auto& e : G[u]) { EST[e.to] = max(EST[e.to], EST[u] + e.cost); } } return EST; } // 最遅開始時刻(LST) vector calc_LST(const vector& revOrder, const Graph& revG, ll T) { int N = revG.size(); const ll INF = 1LL << 60; vector LST(N, INF); LST[revOrder[0]] = T; for (int v : revOrder) { for (const auto& e : revG[v]) { LST[e.from] = min(LST[e.from], LST[v] - e.cost); } } return LST; } int main() { int N, M; cin >> N >> M; Graph G(N), revG(N); for (int i = 0; i < M; ++i) { int u, v; ll c; cin >> u >> v >> c; Edge e = {u, v, c}; G[u].push_back(e); revG[v].push_back(e); } vector topo = topological_sort(G); vector revTopo = topo; reverse(revTopo.begin(), revTopo.end()); vector EST = calc_EST(topo, G); ll T = EST[revTopo[0]]; vector LST = calc_LST(revTopo, revG, T); int slackCount = 0; for (int i = 0; i < N; ++i) { if (LST[i] > EST[i]) slackCount++; } cout << T << " " << slackCount << "/" << N << endl; return 0; }