結果
| 問題 |
No.1442 I-wate Shortest Path Problem
|
| コンテスト | |
| ユーザー |
kwm_t
|
| 提出日時 | 2021-03-31 20:38:15 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 3,803 bytes |
| コンパイル時間 | 2,214 ms |
| コンパイル使用メモリ | 187,276 KB |
| 実行使用メモリ | 43,884 KB |
| 最終ジャッジ日時 | 2024-12-15 08:01:25 |
| 合計ジャッジ時間 | 11,045 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 21 RE * 4 |
ソースコード
#include "bits/stdc++.h"
//#include "atcoder/all"
using namespace std;
//using namespace atcoder;
//using mint = modint1000000007;
//const int mod = 1000000007;
//using mint = modint998244353;
//const int mod = 998244353;
//const int INF = 1e9;
const long long LINF = 1e18;
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define rep2(i,l,r)for(int i=(l);i<(r);++i)
#define rrep(i, n) for (int i = (n-1); i >= 0; --i)
#define rrep2(i,l,r)for(int i=(r-1);i>=(l);--i)
#define all(x) (x).begin(),(x).end()
#define allR(x) (x).rbegin(),(x).rend()
#define endl "\n"
typedef pair<long long, int> P;
class Tree {
public:
Tree(int V, int root) : V(V), root(root) {
T.resize(V);
for (int i = 0; i < MAXLOGV; i++) parent[i].resize(V);
depth.resize(V);
}
// uとvをつなぐ
// lcaを求めることが主目的なので無向グラフとしている
void unite(int u, int v) {
T[u].push_back(v);
T[v].push_back(u);
}
// initする
// コンストラクタだけじゃなくてこれも呼ばないとlcaが求められないぞ
void init() {
dfs(root, -1, 0);
for (int k = 0; k + 1 < MAXLOGV; k++) {
for (int v = 0; v < V; v++) {
if (parent[k][v] < 0) parent[k + 1][v] = -1;
else parent[k + 1][v] = parent[k][parent[k][v]];
}
}
}
// uとvのlcaを求める
int lca(int u, int v) const {
if (depth[u] > depth[v]) swap(u, v);
for (int k = 0; k < MAXLOGV; k++) {
if ((depth[v] - depth[u]) >> k & 1) {
v = parent[k][v];
}
}
if (u == v) return u;
for (int k = MAXLOGV - 1; k >= 0; k--) {
if (parent[k][u] != parent[k][v]) {
u = parent[k][u];
v = parent[k][v];
}
}
return parent[0][u];
}
// uとvの距離を求める
// edgeを定義しないといけない時はこれじゃダメ
int dist(int u, int v) const {
int p = lca(u, v);
return (depth[u] - depth[p]) + (depth[v] - depth[p]);
}
void dfs(int v, int p, int d) {
parent[0][v] = p;
depth[v] = d;
for (int next : T[v]) {
if (next != p) dfs(next, v, d + 1);
}
}
static const int MAXLOGV = 25;
// グラフの隣接リスト表現
vector<vector<int> > T;
// 頂点の数
int V;
// 根ノードの番号
int root;
// 親ノード
vector<int> parent[MAXLOGV];
// 根からの深さ
vector<int> depth;
};
struct Edge {
int to, cost;
Edge(int _to, int _cost) :to(_to), cost(_cost) {}
};
vector<Edge>g0[100005];
vector<Edge>g[100005];
long long d[100005];
long long d2[10][100005];
void dfs(int v, int p = -1) {
for (auto e : g0[v]) {
if (p == e.to) { continue; }
d[e.to] += d[v] + e.cost;
dfs(e.to, v);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, K;
cin >> N >> K;
Tree tree(N, 0);
rep(i, N - 1) {
int a, b, c;
cin >> a >> b >> c;
a--;
b--;
tree.unite(a, b);
g0[a].emplace_back(b, c * 2);
g0[b].emplace_back(a, c * 2);
g[a].emplace_back(b, c * 2);
g[b].emplace_back(a, c * 2);
}
rep(i, K) {
int M, P;
cin >> M >> P;
rep(j, M) {
int x;
cin >> x;
x--;
g[x].emplace_back(i + N, P);
g[i + N].emplace_back(x, P);
}
}
rep(i, N + K) { rep(j, K) { d2[j][i] = LINF; } }
rep(i, K) {
priority_queue<P, vector<P>, greater<P> > q;//小さいもの順
q.emplace(0, i + N);
d2[i][i + N] = 0;
while (!q.empty()) {
auto tmp = q.top();
q.pop();
long long cost = tmp.first;
long long pos = tmp.second;
if (cost > d2[i][pos]) {
continue;
}
for (Edge e : g[pos]) {
if (cost + e.cost < d2[i][e.to]) {
d2[i][e.to] = e.cost + cost;
q.emplace(d2[i][e.to], e.to);
}
}
}
}
tree.init();
dfs(0);
int Q;
cin >> Q;
while (Q--) {
int U, V;
cin >> U >> V;
U--; V--;
long long ans = d[U] + d[V] - 2 * d[tree.lca(U, V)];
rep(i, K) {
ans = min(ans, d2[i][U] + d2[i][V]);
}
ans /= 2;
cout << ans << endl;
}
return 0;
}
kwm_t