HDU 6582 - Path

题目链接:HDU 6582

找到左右可能是最短路的边,利用这些边重新建图求最小割。寻找这些边的方法是,在跑完单源最短路后,\(d_u + c(u, v) = d_v\) 的边就是新图中的边。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template <typename Int>
void getInt(Int &x) {
x = 0; char ch = getchar(); Int sgn = 1;
while (!isdigit(ch)) { if (ch == '-') sgn = -1; ch = getchar(); }
while (isdigit(ch)) { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
x *= sgn;
}
namespace NetworkFlow {
const LL maxn = 10000 * 4 + 100;
LL n, m, s, t, tot;
struct Edge {
LL from, to, cap, flow;
Edge(LL from_ = 0, LL to_ = 0, LL cap_ = 0, LL flow_ = 0)
: from(from_), to(to_), cap(cap_), flow(flow_) {}
};
vector <Edge> edges;
vector <LL> g[maxn];
void addEdge(LL from, LL to, LL cap) {
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, 0, 0));
tot = edges.size();
g[from].push_back(tot - 2);
g[to].push_back(tot - 1);
}
bool vis[maxn];
LL d[maxn], cur[maxn];
queue <LL> q;
bool bfs() {
memset(vis, 0, sizeof vis);
while (!q.empty()) q.pop();
q.push(s); d[s] = 0; vis[s] = 1;
while (!q.empty()) {
LL x = q.front(); q.pop();
for (unsigned i = 0; i < g[x].size(); ++i) {
Edge &e = edges[g[x][i]];
if (!vis[e.to] && e.cap > e.flow) {
vis[e.to] = 1;
d[e.to] = d[x] + 1;
q.push(e.to);
}
}
}
return vis[t];
}
LL dfs(LL x, LL a) {
if (x == t || a == 0) return a;
LL flow = 0, f;
for (LL &i = cur[x]; i < g[x].size(); ++i) {
Edge &e = edges[g[x][i]];
if (d[x] + 1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0) {
e.flow += f; edges[g[x][i] ^ 1].flow -= f;
flow += f; a -= f;
if (!a) break;
}
}
return flow;
}
LL maxFlow() {
LL flow = 0;
while (bfs()) {
memset(cur, 0, sizeof cur);
flow += dfs(s, INT_MAX);
}
return flow;
}
void init() {
edges.clear();
for (LL i = 0; i < maxn; ++i) g[i].clear();
memset(vis, 0, sizeof vis);
memset(d, 0, sizeof d);
memset(cur, 0, sizeof cur);
while (!q.empty()) q.pop();
n = m = s = t = tot = 0;
}
};
const LL MAX_N = 10000 + 5;
LL T, n, m;
struct Edge {
LL from, to, cost;
Edge(LL from_ = 0, LL to_ = 0, LL cost_ = 0)
: from(from_), to(to_), cost(cost_) {}
};
vector <Edge> g[MAX_N];
vector <Edge> edgeVec;
LL d[MAX_N];
void ssspInit() {
for (LL i = 0; i <= n; ++i) {
g[i].clear();
}
edgeVec.clear();
}
struct Status {
LL val, to;
Status(LL val_ = 0, LL to_ = 0)
: val(val_), to(to_) {}
friend bool operator > (const Status &sx, const Status &sy) {
return sx.val > sy.val;
}
};
priority_queue < Status, vector <Status>, greater <Status> > q;
LL dijkstra() {
while (!q.empty()) q.pop();
for (LL i = 1; i <= n; ++i) d[i] = LL(1E18);
d[1] = 0; q.push(Status(0, 1));
while (!q.empty()) {
Status f = q.top(); q.pop();
for (unsigned i = 0; i < g[f.to].size(); ++i) {
Edge &e = g[f.to][i];
if (f.val + e.cost < d[e.to]) {
d[e.to] = f.val + e.cost;
q.push(Status(d[e.to], e.to));
}
}
}
return d[n];
}
int main() {
scanf("%lld", &T);
for (LL cs = 1; cs <= T; ++cs) {
scanf("%lld%lld", &n, &m);
LL u, v, c;
ssspInit();
for (LL i = 1; i <= m; ++i) {
scanf("%lld%lld%lld", &u, &v, &c);
g[u].push_back(Edge(u, v, c));
edgeVec.push_back(Edge(u, v, c));
}
LL sssp = dijkstra();
// cout << "SSSP = " << sssp << endl;
if (sssp == LL(1E18)) {
puts("0");
continue;
}
NetworkFlow::init();
for (auto const &e: edgeVec) {
if (d[e.from] + e.cost == d[e.to]) {
NetworkFlow::addEdge(e.from, e.to, e.cost);
}
}
// NetworkFlow::addEdge(1, 1 + 2, INT_MAX);
// NetworkFlow::addEdge(2, n + 2, INT_MAX);
NetworkFlow::s = 1; NetworkFlow::t = n;
LL ans = NetworkFlow::maxFlow();
printf("%lld\n", ans);
}
return 0;
}