专栏文章
P8240
P8240题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miocc7vi
- 此快照首次捕获于
- 2025/12/02 16:53 3 个月前
- 此快照最后确认于
- 2025/12/02 16:53 3 个月前
整体二分。
先求出来点 到守卫最近的距离 ,然后二分 。
然后问题就变成了是否可以只经过 的点从 到 。
点权不好维护,改成边权的形式,每条边 边权为 ,二分时只连满足 的边 。然后就是判断 是否连通,用并查集维护。
然后这个 次询问复杂度是 的,可以用整体二分优化到 。注意整体二分的时候会对并查集进行撤销操作,因此用可撤销并查集。
CPPconstexpr int N = 1e5 + 5;
ll dis[N];
int n, m, k, Q;
struct Info {
ll x, dis;
bool operator <(const Info& p) const {
return dis > p.dis;
}
} ;
struct Hidesuwa {
int fa[N << 1], dep[N << 1];
stack <tuple <int, int, int> > s;
void Init () {
F (i, 1, n << 1 | 1) fa[i] = i, dep[i] = 1;
}
int Find (int x) {
if (x == fa[x]) return x;
return Find (fa[x]);
}
int Merge (int x, int y) {
int rx = Find (x), ry = Find (y);
if (rx == ry) return 0;
int dx = dep[rx], dy = dep[ry];
if (dx > dy) swap (x, y), swap (rx, ry), swap (dx, dy);
s.push ({rx, ry, dy});
fa[rx] = ry, dep[ry] = max (dx + 1, dy);
return 1;
}
void Rm () {
auto [x, y, d] = s.top (); s.pop ();
fa[x] = x, dep[y] = d;
}
} st;
priority_queue <Info> q;
vector <pair <int, ll> > e[N];
tuple <int, int, ll> t[N << 1];
int p[N];
bitset <N> vis;
void Dijkstra () {
F (i, 1, n) dis[i] = inf;
F (i, 1, k) dis[p[i]] = 0;
F (i, 1, k) {
q.push ({p[i], 0});
}
while (! q.empty ()) {
auto [u, d1] = q.top (); q.pop ();
d1 = dis[u];
if (vis[u] == 1) continue;
vis[u] = 1;
for (auto [v, d2] : e[u]) {
if (dis[v] > d1 + d2) {
dis[v] = d1 + d2;
if (! vis[v]) q.push ({v, d1 + d2});
}
}
}
}
ll ans[N];
void Work (vector <tuple <int, int, int> > v, int s, ll L, ll R) {
if (L == R || ! v.size ()) {
F (i, s, m) {
auto [x, y, d] = t[i];
if (d >= L) st.Merge (x, y);
else break;
}
for (auto [x, y, id] : v) ans[id] = L;
return ;
}
ll m = (L + R + 1) >> 1;
int cnt = 0, pos = s - 1;
F (i, s, :: m) {
auto [x, y, d] = t[i];
if (d >= m) cnt += st.Merge (x, y);
else {
pos = i - 1; break;
}
}
vector <tuple <int, int, int> > v0, v1;
for (auto [x, y, id] : v) {
if (st.Find (x) == st.Find (y)) v0.push_back ({x, y, id});
else v1.push_back ({x, y, id});
}
F (i, 1, cnt) st.Rm ();
Work (v0, s, m, R);
Work (v1, pos + 1, L, m - 1);
}
int main () {
OPEN
IOS
cin >> n >> m;
F (i, 1, m) {
int x, y; ll d; cin >> x >> y >> d;
e[x].push_back ({y, d}), e[y].push_back ({x, d});
t[i] = {x, y, 0};
}
cin >> k;
F (i, 1, k) cin >> p[i];
Dijkstra (); st.Init ();
F (i, 1, m) {
auto [x, y, _] = t[i];
t[i] = {x, y, min (dis[x], dis[y])};
}
sort (t + 1, t + m + 1, [] (tuple <int, int, ll> t1, tuple <int, int, ll> t2) {
auto [x1, y1, d1] = t1;
auto [x2, y2, d2] = t2;
return d1 > d2;
}) ;
vector <tuple <int, int, int> > q;
cin >> Q;
F (i, 1, Q) {
int s, t; cin >> s >> t;
q.push_back ({s, t, i});
}
Work (q, 1, 0, (ll) (1e14));
F (i, 1, Q) cout << max (ans[i] - 1, 0LL) << '\n';
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...