結果
| 問題 |
No.468 役に立つ競技プログラミング実践編
|
| ユーザー |
tubo28
|
| 提出日時 | 2016-12-12 13:39:25 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 550 ms / 2,000 ms |
| コード長 | 3,669 bytes |
| コンパイル時間 | 1,928 ms |
| コンパイル使用メモリ | 183,528 KB |
| 実行使用メモリ | 33,612 KB |
| 最終ジャッジ日時 | 2024-11-30 01:39:09 |
| 合計ジャッジ時間 | 8,610 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 31 |
| other | AC * 6 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(dst, N) for (int dst = 0; dst < (int)(N); ++dst)
#define all(C) begin(C), end(C)
#define dump(x) cerr << __LINE__ << ":\t" #x " = " << x << endl
using Weight = int;
using Capacity = int;
struct Edge {
int src, dst;
Weight weight;
Edge(int s, int d, Weight w) : src(s), dst(d), weight(w) {}
};
using Edges = vector<Edge>;
using Graph = vector<Edges>;
using Array = vector<Weight>;
using Matrix = vector<Array>;
vector<int> tarjan_scc(const Graph &g) {
int n = g.size(), sz = 0;
Graph rg(n);
vector<int> stk, cmp(n, -1), added(n), visited(n), ord(n);
for (auto &es : g) {
for (auto &e : es) rg[e.dst].emplace_back(e.dst, e.src, e.weight);
sz += es.size();
}
stk.resize(n + sz);
sz = 0;
for (int i = 0; i < n; i++) {
if (visited[i]) continue;
int s = 0;
stk[s++] = i;
while (s != 0) {
int v = stk[s - 1];
visited[v] = true;
bool pushed = false;
for (auto &e : g[v]) {
int dst = e.dst;
if (!visited[dst]) {
stk[s++] = dst;
pushed = true;
}
}
if (pushed) continue;
int t = stk[s - 1];
if (!added[t]) {
added[t] = true;
ord[n - ++sz] = t;
}
--s;
}
}
int k = 0;
for (int &u : ord) {
if (cmp[u] != -1) continue;
int s = 0;
stk[s++] = u;
while (s != 0) {
int v = stk[--s];
cmp[v] = k;
for (auto &e : rg[v]) {
int d = e.dst;
if (cmp[d] == -1) stk[s++] = d;
}
}
++k;
}
return cmp;
}
bool in_range(int x, int l, int r) {
return l <= x && x <= r;
}
bool acyclic(const Graph &g) {
vector<int> a = tarjan_scc(g);
sort(all(a));
a.erase(unique(all(a)), a.end());
return a.size();
}
void visit(const Graph &g, int u, int *vis) {
if (vis[u]) return;
vis[u] = true;
for (auto &e : g[u]) visit(g, e.dst, vis);
}
bool all_reachable(const Graph &g, int u) {
static int vis[100010];
memset(vis, 0, sizeof vis);
visit(g, u, vis);
int cnt = count(vis, vis + g.size(), true);
return cnt == g.size();
}
int N, M;
Graph g, rg;
int dpb[100010], dpr[100010];
int blue(int u) {
int &res = dpb[u];
if (res != -1) return res;
res = 0;
for (auto &e : rg[u]) res = max(res, blue(e.dst) + e.weight);
return res;
}
int red(int u) {
int &res = dpr[u];
if (res != -1) return res;
res = 1e9;
for (auto &e : g[u]) res = min(res, red(e.dst) - e.weight);
return res;
}
int main() {
cin >> N >> M;
assert(in_range(N, 3, 100000));
assert(in_range(M, 2, 500000));
g.assign(N, {});
rg.assign(N, {});
memset(dpb, -1, sizeof dpb);
memset(dpr, -1, sizeof dpr);
for (int i = 0; i < M; i++) {
int A, B, C;
cin >> A >> B >> C;
assert(in_range(A, 0, N - 1));
assert(in_range(B, 0, N - 1));
assert(in_range(C, 0, 160 - 1));
g[A].emplace_back(A, B, C);
rg[B].emplace_back(B, A, C);
}
assert(g[N - 1].size() == 0);
assert(rg[0].size() == 0);
assert(acyclic(g));
assert(acyclic(rg));
assert(all_reachable(g, 0));
assert(all_reachable(rg, N - 1));
blue(N - 1);
dpr[N - 1] = dpb[N - 1];
red(0);
int p = 0;
for (int i = 0; i < N; i++) {
if (dpb[i] != dpr[i]) ++p;
}
printf("%d %d/%d\n", blue(N - 1), p, N);
}
tubo28