結果
| 問題 |
No.1442 I-wate Shortest Path Problem
|
| コンテスト | |
| ユーザー |
🍮かんプリン
|
| 提出日時 | 2021-03-29 02:47:14 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 699 ms / 3,000 ms |
| コード長 | 4,265 bytes |
| コンパイル時間 | 2,571 ms |
| コンパイル使用メモリ | 201,428 KB |
| 実行使用メモリ | 37,876 KB |
| 最終ジャッジ日時 | 2024-11-29 09:39:16 |
| 合計ジャッジ時間 | 12,925 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 25 |
ソースコード
/**
* @FileName a.cpp
* @Author kanpurin
* @Created 2021.03.29 02:47:03
**/
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
template<typename T>
struct Dijkstra {
private:
int V;
struct edge { int to; T cost; };
vector<vector<edge>> G;
public:
const T inf = numeric_limits<T>::max();
vector<T> d;
Dijkstra() {}
Dijkstra(int V) : V(V) {
G.resize(V);
}
Dijkstra<T>& operator=(const Dijkstra<T>& obj) {
this->V = obj.V;
this->G = obj.G;
this->d = obj.d;
return *this;
}
void add_edge(int from, int to, T weight, bool directed = false) {
G[from].push_back({to,weight});
if (!directed) G[to].push_back({from,weight});
}
int add_vertex() {
G.push_back(vector<edge>());
return V++;
}
void build(int s) {
d.assign(V, inf);
typedef tuple<T, int> P;
priority_queue<P, vector<P>, greater<P>> pq;
d[s] = 0;
pq.push(P(d[s], s));
while (!pq.empty()) {
P p = pq.top(); pq.pop();
int v = get<1>(p);
if (d[v] < get<0>(p)) continue;
for (const edge &e : G[v])
{
if (d[e.to] > d[v] + e.cost) {
d[e.to] = d[v] + e.cost;
pq.push(P(d[e.to], e.to));
}
}
}
}
};
struct LowestCommonAncestor {
private:
int n;
int log;
struct edge {
edge(int to, int cost) : to(to), cost(cost) {}
int to,cost;
};
vector<vector<int>> parent;
vector<int> dep;
vector<vector<edge>> G;
vector<ll> dis;
void dfs(int v, int p, int d, ll di) {
parent[0][v] = p;
dep[v] = d;
dis[v] = di;
for (edge e : G[v]) {
if (e.to != p) dfs(e.to, v, d + 1,di + e.cost);
}
}
public:
LowestCommonAncestor(int n) : n(n) {
G.resize(n);
}
void add_edge(int from, int to, int cost) {
G[from].push_back(edge(to,cost));
G[to].push_back(edge(from,cost));
}
void build(int root = 0) {
log = log2(n) + 1;
parent.resize(log, vector<int>(n));
dep.resize(n);
dis.resize(n);
dfs(root, -1, 0, 0);
for (int k = 0; k + 1 < log; k++) {
for (int v = 0; v < G.size(); v++) {
if (parent[k][v] < 0) {
parent[k + 1][v] = -1;
}
else {
parent[k + 1][v] = parent[k][parent[k][v]];
}
}
}
}
int depth(int v) {
return dep[v];
}
int lca(int u, int v) {
if (dep[u] > dep[v]) swap(u, v);
for (int k = 0; k < log; k++) if ((dep[v] - dep[u]) >> k & 1) v = parent[k][v];
if (u == v) return u;
for (int k = log - 1; k >= 0; k--) {
if (parent[k][u] != parent[k][v]) {
u = parent[k][u];
v = parent[k][v];
}
}
return parent[0][u];
}
ll dist(int u, int v) {
return dis[u] + dis[v] - 2 * dis[lca(u, v)];
}
};
int main() {
int n,k;cin >> n >> k;
Dijkstra<ll> g(n+k);
LowestCommonAncestor lca(n);
for (int i = 0; i < n-1; i++) {
int a,b,c;cin >> a >> b >> c;
a--;b--;
g.add_edge(a,b,c);
lca.add_edge(a,b,c);
}
vector<int> c(k);
for (int i = 0; i < k; i++) {
int m,p;cin >> m >> p;
c[i] = p;
for (int j = 0; j < m; j++) {
int x;cin >> x;
g.add_edge(x-1,n+i,p,true);
g.add_edge(n+i,x-1,0,true);
}
}
lca.build();
vector<vector<ll>> dist(k);
for (int i = 0; i < k; i++) {
g.build(n+i);
dist[i] = g.d;
}
int q;cin >> q;
constexpr long long LLINF = 1e18 + 1;
while(q--) {
int u,v;cin >> u >> v;
u--;v--;
ll ans = LLINF;
ans = min(ans,lca.dist(u,v));
for (int j = 0; j < k; j++) {
ans = min(ans,dist[j][u] + dist[j][v] + c[j]);
}
cout << ans << endl;
}
return 0;
}
🍮かんプリン