結果
問題 | No.898 tri-βutree |
ユーザー |
![]() |
提出日時 | 2019-10-04 21:37:22 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 996 ms / 4,000 ms |
コード長 | 3,127 bytes |
コンパイル時間 | 2,327 ms |
コンパイル使用メモリ | 196,692 KB |
最終ジャッジ日時 | 2025-01-07 20:25:23 |
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 21 |
ソースコード
#include <bits/stdc++.h>using namespace std;#define INF 100000000#define YJ 1145141919#define INF_INT_MAX 2147483647#define INF_LL 9223372036854775#define INF_LL_MAX 9223372036854775807#define EPS 1e-10#define MOD 1000000007#define MOD9 998244353#define Pi acos(-1)#define LL long long#define ULL unsigned long long#define LD long double#define int long longusing II = pair<int, int>;int gcd(int a, int b) { return b != 0 ? gcd(b, a % b) : a; }int lcm(int a, int b) { return a * b / gcd(a, b); }int extgcd(int a, int b, int &x, int &y) { int g = a; x = 1; y = 0; if (b != 0) g = extgcd(b, a % b, y, x), y -= (a / b) * x; return g; }#define FOR(i,a,b) for(int i=(a);i<(b);++i)#define REP(i,n) FOR(i,0,n)#define ALL(a) begin((a)), end((a))#define RALL(a) (a).rbegin(), (a).rend()#define PB push_back#define MP make_pair#define SZ(a) int((a).size())#define MAX_V 100001#define MAX_LOG_V 17vector<int> Edge[MAX_V]; //辺vector<int> Weight[MAX_V];//parent[k][v]:ノードvにおける親を2^k回巡って//到達する頂点(根を通り過ぎる場合は-1)int parent[MAX_LOG_V][MAX_V];//根からの深さint depth[MAX_V];//vに根とするものを指定すると//parentとdepthを計算してくれる関数//dfs()で0を根とする木とみなすvoid dfs(int v = 0, int p = -1, int d = 0){parent[0][v] = p;depth[v] = d;for(int i = 0; i < (int)Edge[v].size(); i++){if(Edge[v][i] != p){dfs(Edge[v][i], v, d+1);}}}//頂点数Vで初期化void init(int V){//0を根とする木を作成dfs();for(int k = 0; k+1 < MAX_LOG_V; k++){for(int v = 0; v < V; v++){if(parent[k][v] < 0)parent[k+1][v] = -1;elseparent[k+1][v] = parent[k][parent[k][v]];}}}//xとyのLCAを求めるint lca(int x, int y){//yの方が根から深くなるようにするif(depth[x] > depth[y])swap(x,y);//yをxと同じ深さまで持ってくるfor(int k = 0; k < MAX_LOG_V; k++){if(((depth[y] - depth[x]) >> k) & 1){y = parent[k][y];}}//もし既に共通最近祖先にたどり着いたならif(x == y)return x;//二分探索でLCAを求めるfor(int k = MAX_LOG_V - 1; k >= 0; k--){if(parent[k][x] != parent[k][y]){x = parent[k][x];y = parent[k][y];}}return parent[0][x];}int N;void addEdge(int x, int y, int z) {Edge[x].push_back(y);Weight[x].push_back(z);}int sumW[MAX_V];void calcSumW(int pos = 0, int pre = -1, int w = 0){sumW[pos] = w;REP(n,Edge[pos].size()) {int next = Edge[pos][n];int ww = Weight[pos][n];if(next == pre) continue;calcSumW(next, pos, ww + w);}}signed main(){cin >> N;REP(n,N-1) {int x, y, z; cin >> x >> y >> z;addEdge(x,y,z);addEdge(y,x,z);}init(N);calcSumW();int Q;cin >> Q;REP(q,Q) {int x[3]; cin >> x[0] >> x[1] >> x[2];int ans = 0;REP(n,3) {int y = x[n], z = x[(n+1)%3];int root = lca(y, z);ans += sumW[y] + sumW[z] - 2 * sumW[root];}cout << ans/2 << endl;}return 0;}