結果
| 問題 |
No.654 Air E869120
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-04-30 00:53:06 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 20 ms / 2,000 ms |
| コード長 | 4,666 bytes |
| コンパイル時間 | 1,315 ms |
| コンパイル使用メモリ | 118,956 KB |
| 実行使用メモリ | 5,248 KB |
| 最終ジャッジ日時 | 2024-11-30 17:48:59 |
| 合計ジャッジ時間 | 2,917 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 35 |
ソースコード
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>
using namespace std;
#define rep(i, n) for (int64_t i = 0; i < (n); i++)
#define irep(i, n) for (int64_t i = 0; i <= (n); i++)
#define rrep(i, n) for (int64_t i = (n)-1; i >= 0; i--)
#define rirep(i, n) for (int64_t i = n; i >= 0; i--)
struct Edge {
int from;
int to;
int64_t capacity;
int64_t flow;
};
void maxflow(const vector<vector<int>> &outEdge,
const vector<vector<int>> &inEdge, vector<Edge> &edgeData,
const int source, const int sink) {
const int n = outEdge.size();
const int m = edgeData.size();
while (true) {
// check if reachable to sink
vector<int> parent(n, -1);
queue<int> q;
q.push(source);
while (!q.empty()) {
int v = q.front();
q.pop();
for (const int e : outEdge[v]) {
const Edge &data = edgeData[e];
const int nv = data.to;
if (parent[nv] < 0 && data.capacity - data.flow > 0) {
q.push(nv);
parent[nv] = e;
}
}
for (const int e : inEdge[v]) {
const Edge &data = edgeData[e];
const int nv = data.from;
if (parent[nv] < 0 && data.flow > 0) {
q.push(nv);
parent[nv] = e;
}
}
}
if (parent[sink] < 0) {
break;
}
// select path from source to sink
int64_t d = 1'000'000'000;
int v = sink;
while (v != source) {
const int e = parent[v];
const Edge &data = edgeData[e];
if (data.to == v) {
d = min(d, data.capacity - data.flow);
v = data.from;
} else {
d = min(d, data.flow);
v = data.to;
}
}
// update flow on the path
v = sink;
while (v != source) {
const int e = parent[v];
Edge &data = edgeData[e];
if (data.to == v) {
data.flow += d;
v = data.from;
} else {
data.flow -= d;
v = data.to;
}
}
}
}
int main() {
int N, M, d;
cin >> N >> M >> d;
using Plane = tuple<int, int, int, int, int>;
const int TMAX = 1'000'000'000;
const int64_t INF = 1'000L * 1'000'000'000;
vector<Plane> planes(M);
vector<vector<int>> departures(N);
rep(i, M) {
int u, v, p, q, w;
cin >> u >> v >> p >> q >> w;
u--;
v--;
planes[i] = Plane(u, v, p, q + d, w);
departures[u].push_back(p);
}
departures[0].push_back(0);
departures[N - 1].push_back(TMAX + d);
rep(i, N) {
sort(departures[i].begin(), departures[i].end());
departures[i].erase(unique(departures[i].begin(), departures[i].end()),
departures[i].end());
}
int nodeNum = 0;
vector<vector<int>> ids(N);
rep(i, N) {
for (const int d : departures[i]) {
ids[i].push_back(nodeNum);
nodeNum++;
}
}
vector<vector<int>> outEdge(nodeNum), inEdge(nodeNum);
vector<Edge> edgeData;
int edgeNum = 0;
// edges representing moving by plane
rep(i, M) {
int u, v, p, q, w;
tie(u, v, p, q, w) = planes[i];
auto fromAddr = lower_bound(departures[u].begin(), departures[u].end(), p);
auto toAddr = lower_bound(departures[v].begin(), departures[v].end(), q);
if (toAddr != departures[v].end()) {
int fromId = ids[u][fromAddr - departures[u].begin()];
int toId = ids[v].at(toAddr - departures[v].begin());
outEdge[fromId].push_back(edgeNum);
inEdge[toId].push_back(edgeNum);
Edge eData;
eData.from = fromId;
eData.to = toId;
eData.flow = 0;
eData.capacity = w;
edgeData.push_back(eData);
edgeNum++;
}
}
cerr << "------------------------------" << endl;
for (const Edge &data : edgeData) {
cerr << data.from << " " << data.to << "\t" << data.flow << " / "
<< data.capacity << endl;
}
cerr << "------------------------------" << endl;
// edges representing staying in a city
rep(i, N) {
const int tNum = departures[i].size();
rep(j, tNum - 1) {
int fromId = ids[i][j];
int toId = ids[i][j + 1];
outEdge[fromId].push_back(edgeNum);
inEdge[toId].push_back(edgeNum);
Edge eData;
eData.from = fromId;
eData.to = toId;
eData.flow = 0;
eData.capacity = INF;
edgeData.push_back(eData);
edgeNum++;
}
}
const int source = 0;
const int sink = nodeNum - 1;
maxflow(outEdge, inEdge, edgeData, source, sink);
int64_t result = 0;
for (const int e : inEdge[sink]) {
result += edgeData[e].flow;
}
cout << result << endl;
return 0;
}