結果
| 問題 |
No.529 帰省ラッシュ
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2018-09-26 01:22:53 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 482 ms / 4,500 ms |
| コード長 | 9,061 bytes |
| コンパイル時間 | 2,605 ms |
| コンパイル使用メモリ | 230,140 KB |
| 最終ジャッジ日時 | 2025-01-06 13:47:03 |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 18 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int inf = 1e9;
struct edge {
int from, to;
};
using graph = vector<vector<edge>>;
void add_edge(graph& g, int from, int to) {
g[from].push_back(edge{from, to});
g[to].push_back(edge{to, from});
}
class heavy_light_decomposition {
public:
heavy_light_decomposition(int n_)
: n(n_), g(n), par(n), head(n), in(n), out(n)
{}
heavy_light_decomposition(std::vector<std::vector<int>> const& g_)
: n(g_.size()), g(g_), par(n), head(n), in(n), out(n)
{}
void add_edge(int u, int v) {
g[u].push_back(v);
g[v].push_back(u);
}
void build(int rt = 0) {
dfs1(rt);
head[rt] = rt;
dfs2(rt);
}
int get_id(int v) const { return in[v]; }
void path_query(int u, int v, std::function<void(int, int)> f) { // vertex
while(true) {
if(in[u] > in[v]) std::swap(u, v);
f(std::max(in[head[v]], in[u]), in[v] + 1);
if(head[u] == head[v]) return;
v = par[head[v]];
}
}
void edge_path_query(int u, int v, std::function<void(int, int)> f) {
while(true) {
if(in[u] > in[v]) std::swap(u, v);
if(head[u] != head[v]) {
f(std::max(in[head[v]], in[u]), in[v] + 1);
v = par[head[v]];
} else {
if(u != v) f(in[u] + 1, in[v] + 1);
break;
}
}
}
void subtree_query(int v, std::function<void(int, int)> f) {
f(in[v], out[v]);
}
int get_lca(int u, int v) const {
while(true) {
if(in[u] > in[v]) std::swap(u, v);
if(head[u] == head[v]) return u;
v = par[head[v]];
}
}
private:
void dfs1(int rt) {
std::vector<int> sz(n, 1), iter(n);
std::vector<std::pair<int, int>> st = {{rt, -1}};
st.reserve(n);
while(!st.empty()) {
const int v = st.back().first;
if(iter[v] < (int)g[v].size()) {
if(g[v][iter[v]] != st.back().second) {
st.emplace_back(g[v][iter[v]], v);
}
++iter[v];
continue;
}
par[v] = st.back().second;
if(par[v] != -1) {
const int pidx = std::find(std::begin(g[v]), std::end(g[v]), par[v]) - std::begin(g[v]);
std::swap(g[v].back(), g[v][pidx]);
g[v].pop_back();
}
for(auto& u : g[v]) {
sz[v] += sz[u];
if(sz[u] > sz[g[v].front()]) std::swap(u, g[v].front());
}
st.pop_back();
}
}
void dfs2(int rt) {
int it = 0;
std::vector<int> st = {rt}, iter(n);
st.reserve(n);
while(!st.empty()) {
const int v = st.back();
if(!iter[v]) in[v] = it++; // first visit
if(iter[v] < (int)g[v].size()) {
int u = g[v][iter[v]];
head[u] = iter[v] ? u : head[v];
st.push_back(u);
++iter[v];
continue;
}
out[v] = it;
st.pop_back();
}
}
private:
const int n;
std::vector<std::vector<int>> g;
std::vector<int> par, head, in, out;
};
class lowlink { // multiple edges ok
public:
lowlink(graph const& g)
: ord(g.size()), low(g.size())
{
const int n = g.size();
std::vector<bool> visited(n);
int cnt = 0;
for(int i = 0; i < n; ++i) {
if(!visited[i]) {
dfs(g, i, -1, cnt, visited);
}
}
}
std::vector<int> get_articulation_points() const { return articulation_points; }
std::vector<edge> get_bridges() const { return bridges; }
bool is_bridge(int u, int v) const {
if(ord[u] > ord[v]) std::swap(u, v);
return ord[u] < low[v];
}
private:
void dfs(graph const& g, int v, int prev, int& cnt, std::vector<bool>& visited) {
visited[v] = true;
low[v] = ord[v] = cnt++;
bool is_articulation = false;
int cnt2 = 0, pcnt = 0;
for(auto& e : g[v]) {
if((e.to != prev || (e.to == prev && pcnt == 1)) && visited[e.to]) {
low[v] = min(low[v], ord[e.to]);
} else if(!visited[e.to]) {
cnt2++;
dfs(g, e.to, v, cnt, visited);
low[v] = min(low[v], low[e.to]);
if(prev != -1 && ord[v] <= low[e.to]) {
is_articulation = true;
}
if(is_bridge(v, e.to)) {
bridges.push_back(edge{min(v, e.to), max(v, e.to)});
}
}
pcnt += e.to == prev;
}
is_articulation |= (prev == -1 && cnt2 > 1);
if(is_articulation) articulation_points.push_back(v);
}
private:
std::vector<int> articulation_points;
std::vector<edge> bridges;
std::vector<int> ord, low;
};
class biconnected_component {
public:
biconnected_component(graph const& g_)
: g(g_), helper(g_), belongs_(g_.size(), -1)
{
for(auto&& b : helper.get_bridges()) {
add_component(b.from), add_component(b.to);
}
add_component(0);
}
graph build() { // if not connected, result is forest
graph res(cmps.size());
auto bridges = helper.get_bridges();
for(auto& b : bridges) {
add_edge(res, belongs(b.from), belongs(b.to));
}
return res;
}
int belongs(int u) const { return belongs_[u]; }
private:
void fill_component(int c, int u) {
cmps[c].emplace_back(u);
belongs_[u] = c;
for(auto& e : g[u]) {
if(belongs_[e.to] >= 0 || helper.is_bridge(u, e.to)) continue;
fill_component(c, e.to);
}
}
void add_component(int u) {
if(belongs_[u] >= 0) return;
cmps.emplace_back();
fill_component(cmps.size() - 1, u);
}
private:
graph g;
lowlink helper;
std::vector<int> belongs_;
std::vector<std::vector<int>> cmps;
};
template<typename Monoid>
class segment_tree {
using T = typename Monoid::type;
public:
segment_tree(std::vector<T> const& init)
: sz(init.size()), n(expand(init.size()))
{
dat.assign(n * 2, Monoid::id());
std::copy(begin(init), end(init), begin(dat) + n);
for(int i = n - 1; i >= 0; --i) {
dat[i] = Monoid::op(dat[i * 2], dat[i * 2 + 1]);
}
}
segment_tree(int const n_, T const& init = Monoid::id())
: segment_tree(std::vector<T>(n_, init))
{}
void update(int p, T val) {
assert(0 <= p && p < sz);
dat[p += n] = val;
while(p /= 2) {
dat[p] = Monoid::op(dat[p * 2], dat[p * 2 + 1]);
}
}
// [l, r)
T query(int l, int r) const {
assert(0 <= l && l <= r && r <= sz);
l += n, r += n;
T res1 = Monoid::id(), res2 = Monoid::id();
while(l != r) {
if(l & 1) res1 = Monoid::op(res1, dat[l++]);
if(r & 1) res2 = Monoid::op(dat[--r], res2);
l /= 2, r /= 2;
}
return Monoid::op(res1, res2);
}
private:
int expand(int n_) const {
assert(n_ >= 1);
return n_ == 1 ? n_ : expand((n_ + 1) / 2) * 2;
}
private:
const int sz, n;
std::vector<T> dat;
};
struct RMQ {
using type = int;
static type id() {
return -1;
}
static type op(type const& l, type const& r) {
return std::max(l, r);
}
};
int main() {
ios_base::sync_with_stdio(false); cin.tie(0);
int n, m, q; cin >> n >> m >> q;
graph g(n);
vector<int> a(m), b(m);
for(int i = 0; i < m; ++i) {
cin >> a[i] >> b[i];
a[i]--, b[i]--;
add_edge(g, a[i], b[i]);
}
biconnected_component bicc(g);
g = bicc.build();
n = g.size();
heavy_light_decomposition hld(n);
for(auto& es : g) {
for(auto& e : es) {
if(e.from < e.to) hld.add_edge(e.from, e.to);
}
}
hld.build();
segment_tree<RMQ> seg(n);
vector<priority_queue<int>> qs(n);
map<int, int> w_to_v;
for(int i = 0; i < q; ++i) {
int qtype; cin >> qtype;
if(qtype == 1) {
int u, w; cin >> u >> w;
u = hld.get_id(bicc.belongs(u - 1));
w_to_v[w] = u;
qs[u].push(w);
seg.update(u, qs[u].top());
} else {
int s, t; cin >> s >> t;
s = bicc.belongs(s - 1), t = bicc.belongs(t - 1);
int ans = -1;
hld.path_query(s, t, [&] (int l, int r) { ans = max(ans, seg.query(l, r)); });
cout << ans << endl;
if(ans == -1) continue;
const int v = w_to_v[ans];
qs[v].pop();
seg.update(v, qs[v].empty() ? -1 : qs[v].top());
}
}
}