結果
| 問題 |
No.1600 Many Shortest Path Problems
|
| コンテスト | |
| ユーザー |
SSRS
|
| 提出日時 | 2021-07-09 23:29:32 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 5,216 bytes |
| コンパイル時間 | 2,527 ms |
| コンパイル使用メモリ | 194,368 KB |
| 実行使用メモリ | 41,088 KB |
| 最終ジャッジ日時 | 2024-07-01 18:25:51 |
| 合計ジャッジ時間 | 28,209 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | -- * 3 |
| other | AC * 30 TLE * 1 -- * 20 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
const int LOG = 18;
const int INF = 10000000;
const long long MOD = 1000000007;
struct unionfind{
vector<int> p;
unionfind(int N){
p = vector<int>(N, -1);
}
int root(int x){
if (p[x] < 0){
return x;
} else {
p[x] = root(p[x]);
return p[x];
}
}
bool same(int x, int y){
return root(x) == root(y);
}
void unite(int x, int y){
x = root(x);
y = root(y);
if (x != y){
if (p[x] < p[y]){
swap(x, y);
}
p[y] += p[x];
p[x] = y;
}
}
};
struct dual_segment_tree{
int N;
vector<int> ST;
dual_segment_tree(){
}
dual_segment_tree(int N2){
N = 1;
while (N < N2){
N *= 2;
}
ST = vector<int>(N * 2 - 1, INF);
}
int operator [](int k){
k += N - 1;
int ans = ST[k];
while (k > 0){
k = (k - 1) / 2;
ans = min(ans, ST[k]);
}
return ans;
}
void range_chmin(int L, int R, int x, int i, int l, int r){
if (r <= L || R <= l){
return;
} else if (L <= l && r <= R){
ST[i] = min(ST[i], x);
} else {
int m = (l + r) / 2;
range_chmin(L, R, x, i * 2 + 1, l, m);
range_chmin(L, R, x, i * 2 + 2, m, r);
}
}
void range_chmin(int L, int R, int x){
range_chmin(L, R, x, 0, 0, N);
}
};
struct heavy_light_decomposition{
vector<int> p, sz, in, next;
vector<int> d1;
vector<long long> d2;
dual_segment_tree ST;
heavy_light_decomposition(vector<int> &p, vector<vector<pair<long long, int>>> &c): p(p){
int N = p.size();
sz = vector<int>(N, 0);
d1 = vector<int>(N, 0);
d2 = vector<long long>(N, 0);
dfs1(c);
in = vector<int>(N, 0);
next = vector<int>(N, 0);
int t = 0;
dfs2(c, t);
ST = dual_segment_tree(N);
}
void dfs1(vector<vector<pair<long long, int>>> &c, int v = 0){
sz[v] = 1;
for (auto &P : c[v]){
int w = P.second;
d1[w] = d1[v] + 1;
d2[w] = d2[v] + P.first;
dfs1(c, w);
if (sz[w] > sz[c[v][0].second]){
swap(P, c[v][0]);
}
}
}
void dfs2(vector<vector<pair<long long, int>>> &c, int &t, int v = 0){
in[v] = t;
t++;
for (auto P : c[v]){
int w = P.second;
if (P == c[v][0]){
next[w] = next[v];
} else {
next[w] = w;
}
dfs2(c, t, w);
}
}
int lca(int x, int y){
while (true){
if (in[x] > in[y]){
swap(x, y);
}
if (next[x] == next[y]){
return x;
}
y = p[next[y]];
}
}
int dist1(int x, int y){
return d1[x] + d1[y] - 2 * d1[lca(x, y)];
}
long long dist2(int x, int y){
return d2[x] + d2[y] - 2 * d2[lca(x, y)];
}
int operator [](int v){
return ST[in[v]];
}
void path_chmin(int u, int v, int x){
int w = lca(u, v);
while (next[u] != next[w]){
ST.range_chmin(in[next[u]], in[u] + 1, x);
u = p[next[u]];
}
ST.range_chmin(in[w] + 1, in[u] + 1, x);
while (next[v] != next[w]){
ST.range_chmin(in[next[v]], in[v] + 1, x);
v = p[next[v]];
}
ST.range_chmin(in[w] + 1, in[v] + 1, x);
}
};
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, M;
cin >> N >> M;
vector<pair<int, int>> E(M);
for (int i = 0; i < M; i++){
int A, B;
cin >> A >> B;
A--;
B--;
E[i] = make_pair(A, B);
}
vector<long long> cost(M);
cost[0] = 2;
for (int i = 1; i < M; i++){
cost[i] = cost[i - 1] * 2 % MOD;
}
unionfind UF(N);
vector<bool> span(M, false);
vector<vector<pair<long long, int>>> E2(N);
for (int i = 0; i < M; i++){
int A = E[i].first;
int B = E[i].second;
if (!UF.same(A, B)){
span[i] = true;
UF.unite(A, B);
E2[A].push_back(make_pair(cost[i], B));
E2[B].push_back(make_pair(cost[i], A));
}
}
vector<int> p(N, -1);
vector<vector<pair<long long, int>>> c(N);
vector<int> d(N, 0);
queue<int> q;
q.push(0);
while (!q.empty()){
int v = q.front();
q.pop();
for (auto P : E2[v]){
int w = P.second;
if (w != p[v]){
p[w] = v;
c[v].push_back(P);
d[w] = d[v] + 1;
q.push(w);
}
}
}
heavy_light_decomposition T(p, c);
for (int i = 0; i < M; i++){
if (!span[i]){
int A = E[i].first;
int B = E[i].second;
T.path_chmin(A, B, i);
}
}
int Q;
cin >> Q;
for (int i = 0; i < Q; i++){
int x, y, z;
cin >> x >> y >> z;
x--;
y--;
z--;
int a = E[z].first;
int b = E[z].second;
if (!span[z]){
cout << T.dist2(x, y) % MOD << "\n";
} else {
int d1 = T.dist1(x, a) + T.dist1(b, y);
int d2 = T.dist1(x, b) + T.dist1(a, y);
int d3 = T.dist1(x, y);
if (d1 + 1 != d3 && d2 + 1 != d3){
cout << T.dist2(x, y) % MOD << "\n";
} else {
if (b == p[a]){
swap(a, b);
}
int mn = T[b];
if (mn == INF){
cout << -1 << "\n";
} else {
int c = E[mn].first;
int d = E[mn].second;
long long ans1 = T.dist2(x, c) + cost[mn] + T.dist2(d, y);
long long ans2 = T.dist2(x, d) + cost[mn] + T.dist2(c, y);
cout << min(ans1, ans2) % MOD << "\n";
}
}
}
}
}
SSRS