QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#282352 | #3249. 分组作业 | kilo_tobo_tarjen# | TL | 0ms | 0kb | C++20 | 8.9kb | 2023-12-11 20:53:07 | 2023-12-11 20:53:08 |
answer
#include <bits/stdc++.h>
// #include <bits/extc++.h>
// using namespace __gnu_cxx;
// using namespace __gnu_pbds;
using i64 = long long;
using namespace std;
const int N = 1e4 + 5;
// const int B = 1250;
// const int M = 105;
// const int base = 17131;
// const int mod = 998244353;
// const int mod = 1e9 + 7;
// const long double pi = acosl(-1);
namespace maxflow
{
typedef long long flow_t;
const flow_t inf_flow = 1e9;
const int inf_dep = 1e9;
struct FlowEdge
{
int from, to;
flow_t cap, low = 0, flow = 0;
};
int num_node(const std::vector<FlowEdge> &edges)
{
int n = 0;
for (const auto &e : edges)
n = std::max({n, e.from, e.to});
return n;
}
flow_t get_flow(const std::vector<FlowEdge> &edges, int s)
{
flow_t flow = 0;
for (const auto &e : edges)
{
if (e.from == s)
flow += e.flow;
}
return flow;
}
struct MaxFlow
{
struct Edge
{
int from, to;
flow_t cap;
};
int n;
std::vector<std::vector<int>> eid;
std::vector<Edge> edge;
void build(const std::vector<FlowEdge> &edges)
{
n = num_node(edges);
eid.assign(n + 1, {});
edge.clear();
int num_edges = 0;
for (const auto &e : edges)
{
eid[e.from].push_back(num_edges++);
edge.push_back({e.from, e.to, e.cap - e.flow});
eid[e.to].push_back(num_edges++);
edge.push_back({e.to, e.from, e.flow});
}
}
std::vector<int> dis;
std::vector<int> cur;
bool bfs(int s, int t)
{
if (s > n || t > n)
return false;
dis.assign(n + 1, inf_dep);
cur.assign(n + 1, 0);
std::queue<int> que;
dis[s] = 0;
que.push(s);
while (que.size())
{
int u = que.front();
que.pop();
for (auto i : eid[u])
{
const auto &e = edge[i];
if (e.cap && dis[e.to] > dis[u] + 1)
{
dis[e.to] = dis[u] + 1;
que.push(e.to);
}
}
}
return dis[t] < inf_dep;
}
flow_t dfs(int s, int t, flow_t flim)
{
if (s == t)
return flim;
flow_t flow = 0;
for (int &i = cur[s]; i < eid[s].size() && flow < flim; i++)
{
auto &e = edge[eid[s][i]];
if (dis[e.to] == dis[s] + 1 && e.cap)
{
auto detf = dfs(e.to, t, std::min(flim - flow, e.cap));
flow += detf;
e.cap -= detf;
edge[eid[s][i] ^ 1].cap += detf;
}
if (flow == flim)
break;
}
return flow;
}
flow_t maxflow(int s, int t)
{
flow_t flow = 0;
while (bfs(s, t))
{
flow += dfs(s, t, inf_flow);
}
return flow;
}
std::vector<FlowEdge> to_edge()
{
std::vector<FlowEdge> edges;
for (int i = 0; i < edge.size(); i += 2)
edges.push_back({
.from = edge[i].from,
.to = edge[i].to,
.cap = edge[i].cap + edge[i ^ 1].cap,
.low = 0,
.flow = edge[i ^ 1].cap,
});
return edges;
}
};
struct Processor
{
std::vector<bool> neg;
std::vector<flow_t> low;
std::vector<flow_t> excess;
void init(std::vector<FlowEdge> &edges)
{
int n = num_node(edges);
neg.clear();
neg.reserve(edges.size());
low.clear();
low.reserve(edges.size());
excess.assign(n + 1, 0);
}
void rmv_low(std::vector<FlowEdge> &edges)
{
for (auto &e : edges)
{
low.push_back(e.low);
if (e.flow >= e.low)
{
e.flow -= e.low;
}
else
{
excess[e.from] -= e.low - e.flow;
excess[e.to] += e.low - e.flow;
e.flow = 0;
}
e.cap -= e.low;
e.low = 0;
}
}
void add_low(std::vector<FlowEdge> &edges)
{
reverse(low.begin(), low.end());
for (auto &e : edges)
{
e.low = low.back();
e.flow += e.low;
e.cap += e.low;
low.pop_back();
}
}
};
bool excess_flow(std::vector<FlowEdge> &edges,
const std::vector<flow_t> &excess)
{
int n = num_node(edges), m = edges.size();
for (int i = 1; i <= n; i++)
{
if (excess[i] > 0)
edges.push_back({.from = n + 1, .to = i, .cap = excess[i]});
if (excess[i] < 0)
edges.push_back({.from = i, .to = n + 2, .cap = -excess[i]});
}
MaxFlow g;
g.build(edges);
g.maxflow(n + 1, n + 2);
edges = g.to_edge();
for (int i = m; i < edges.size(); i++)
if (edges[i].flow != edges[i].cap)
return false;
edges.resize(m);
return true;
}
std::optional<flow_t> feasible_flow(std::vector<FlowEdge> &edges, int s = 0,
int t = 0)
{
if (s && t)
edges.push_back({.from = t, .to = s, .cap = inf_flow});
Processor p;
p.init(edges);
p.rmv_low(edges);
if (!excess_flow(edges, p.excess))
return std::nullopt;
if (s && t)
edges.pop_back();
p.add_low(edges);
return get_flow(edges, s);
}
std::optional<flow_t> maximum_flow(std::vector<FlowEdge> &edges, int s, int t)
{
edges.push_back({.from = t, .to = s, .cap = inf_flow});
Processor p;
p.init(edges);
p.rmv_low(edges);
if (!excess_flow(edges, p.excess))
return std::nullopt;
edges.pop_back();
MaxFlow g;
g.build(edges);
g.maxflow(s, t);
edges = g.to_edge();
p.add_low(edges);
return get_flow(edges, s);
}
std::optional<flow_t> minimum_flow(std::vector<FlowEdge> &edges, int s, int t)
{
edges.push_back({.from = t, .to = s, .cap = inf_flow});
Processor p;
p.init(edges);
p.rmv_low(edges);
if (!excess_flow(edges, p.excess))
return std::nullopt;
edges.pop_back();
MaxFlow g;
Processor q;
excess_flow(edges, q.excess);
g.build(edges);
g.maxflow(t, s);
edges = g.to_edge();
p.add_low(edges);
return get_flow(edges, s);
}
} // namespace maxflow
// ed.push_back({.from=x, .to=y, .cap=z});
using namespace maxflow;
int n, m, c[N], d[N], e[N];
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n * 2; i++)
cin >> c[i] >> d[i] >> e[i];
vector<FlowEdge> E;
int S = 0, T = 3 * n + 1;
for (int i = 1; i <= n; i++)
{
E.push_back({.from = S, .to = 3 * i - 2, .cap = inf_flow * 2 + c[2 * i - 1] + c[2 * i]});
E.push_back({.from = 3 * i - 2, .to = 3 * i - 1, .cap = inf_flow + c[2 * i - 1]});
E.push_back({.from = 3 * i - 2, .to = 3 * i, .cap = inf_flow + c[2 * i]});
E.push_back({.from = 3 * i - 1, .to = 3 * i, .cap = inf_flow + e[2 * i - 1]});
E.push_back({.from = 3 * i, .to = 3 * i - 1, .cap = inf_flow + e[2 * i]});
E.push_back({.from = 3 * i - 1, .to = T, .cap = inf_flow + d[2 * i - 1]});
E.push_back({.from = 3 * i, .to = T, .cap = inf_flow + d[2 * i]});
}
for (int i = 1, a, b, x, y; i <= m; i++)
{
cin >> a >> b;
E.push_back({.from = 3 * ((a + 1) / 2) - 1, .to = 3 * ((b + 1) / 2) - 2, .cap = x});
E.push_back({.from = 3 * ((a + 1) / 2) - 2, .to = 3 * ((b + 1) / 2), .cap = y});
}
auto G = maximum_flow(E, S, T);
i64 ans = *G - inf_flow * n * 2;
cout << ans << '\n';
}
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
// cin >> t;
cout << fixed << setprecision(10);
while (t--)
solve();
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Time Limit Exceeded
input:
5000 10000 23060775 12 2 255978380 28 517 5 6624 26 151149 45131806 23849036 489 484971 24970 162846 1993316 188305 56311199 2003 211 1 50534913 517527 364913 882765 298 71 26 122914059 13 65459 18150033 20 607 8 380059068 3873712 228 9813 5449 6370 3309369 37410691 8 181 1 62340851 1705 4 107 8 209...