結果
問題 | No.1002 Twotone |
ユーザー | chocorusk |
提出日時 | 2020-02-28 22:49:11 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,435 ms / 5,000 ms |
コード長 | 4,023 bytes |
コンパイル時間 | 1,621 ms |
コンパイル使用メモリ | 136,436 KB |
実行使用メモリ | 39,680 KB |
最終ジャッジ日時 | 2024-10-13 18:41:39 |
合計ジャッジ時間 | 19,053 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 5 ms
8,192 KB |
testcase_01 | AC | 5 ms
8,320 KB |
testcase_02 | AC | 5 ms
8,320 KB |
testcase_03 | AC | 280 ms
15,360 KB |
testcase_04 | AC | 351 ms
17,536 KB |
testcase_05 | AC | 355 ms
17,536 KB |
testcase_06 | AC | 5 ms
8,320 KB |
testcase_07 | AC | 367 ms
13,952 KB |
testcase_08 | AC | 678 ms
17,408 KB |
testcase_09 | AC | 688 ms
17,536 KB |
testcase_10 | AC | 5 ms
8,192 KB |
testcase_11 | AC | 757 ms
16,000 KB |
testcase_12 | AC | 1,050 ms
18,176 KB |
testcase_13 | AC | 1,079 ms
18,248 KB |
testcase_14 | AC | 4 ms
8,320 KB |
testcase_15 | AC | 537 ms
13,952 KB |
testcase_16 | AC | 1,091 ms
18,116 KB |
testcase_17 | AC | 1,082 ms
18,176 KB |
testcase_18 | AC | 5 ms
8,448 KB |
testcase_19 | AC | 623 ms
24,516 KB |
testcase_20 | AC | 752 ms
34,816 KB |
testcase_21 | AC | 747 ms
33,988 KB |
testcase_22 | AC | 4 ms
8,448 KB |
testcase_23 | AC | 795 ms
27,904 KB |
testcase_24 | AC | 1,429 ms
39,680 KB |
testcase_25 | AC | 1,435 ms
39,552 KB |
testcase_26 | AC | 4 ms
8,192 KB |
testcase_27 | AC | 85 ms
17,184 KB |
testcase_28 | AC | 129 ms
20,676 KB |
testcase_29 | AC | 125 ms
20,548 KB |
testcase_30 | AC | 4 ms
8,192 KB |
testcase_31 | AC | 122 ms
20,628 KB |
testcase_32 | AC | 138 ms
20,804 KB |
testcase_33 | AC | 130 ms
20,676 KB |
testcase_34 | AC | 1,071 ms
33,536 KB |
ソースコード
#include <cstdio> #include <cstring> #include <iostream> #include <string> #include <cmath> #include <bitset> #include <vector> #include <map> #include <set> #include <queue> #include <deque> #include <algorithm> #include <complex> #include <unordered_map> #include <unordered_set> #include <random> #include <cassert> #include <fstream> #include <utility> #include <functional> #include <time.h> #include <stack> #include <array> #define popcount __builtin_popcount using namespace std; typedef long long int ll; typedef pair<int, int> P; const int MAX_V = 200020; // ツリーのサイズのありうる最大値 int N; // ツリーのサイズ vector<P> tree[MAX_V]; // ツリーを隣接リスト形式のグラフ構造で表したもの int sizeSubtree[MAX_V]; // sizeSubtree[v] := v を根とする部分ツリーのサイズ (分割統治の毎ステップごとに再利用) bool isRemoved[MAX_V]; // isRemoved[v] := v が既に取り除かれたかどうか int whoIsParent[MAX_V]; // whoIsParent[v] := ツリーDP時に v の親が誰だったか // メイン処理 vector<int> centroids; void FindCentroidRecursive(int v, int size, int p = -1) { sizeSubtree[v] = 1; whoIsParent[v] = p; bool isCentroid = true; for (auto pr : tree[v]) { int ch=pr.first; if (ch == p) continue; if (isRemoved[ch]) continue; FindCentroidRecursive(ch, size, v); if (sizeSubtree[ch] > size / 2) isCentroid = false; sizeSubtree[v] += sizeSubtree[ch]; } if (size - sizeSubtree[v] > size / 2) isCentroid = false; if (isCentroid) centroids.push_back(v); } // 初期化 void Init() { for (int i = 0; i < MAX_V; ++i) { isRemoved[i] = false; } } // first: 重心, second: (重心の子ノード, 子部分木のサイズ) からなるベクトル pair<int, vector<pair<int,int> > > FindCentroid(int root, int size) { vector<pair<int, int> > subtrees; centroids.clear(); FindCentroidRecursive(root, size); int center = centroids[0]; for (auto pr : tree[center]) { int ch=pr.first; if (isRemoved[ch]) continue; if (ch == whoIsParent[center]) { subtrees.push_back(make_pair(ch, size - sizeSubtree[center])); } else { subtrees.push_back(make_pair(ch, sizeSubtree[ch])); } } return make_pair(center, subtrees); } map<P, ll> mp1; map<int, ll> mp2; void dfs(int v, int p, vector<int> vc){ //whoIsParent[v] = p; if(vc.size()==1) mp2[vc[0]]++; else if(vc.size()==2) mp1[{vc[0], vc[1]}]++; for(auto pr:tree[v]){ int ch=pr.first; if (ch == p) continue; if (isRemoved[ch]) continue; vector<int> vc2=vc; vc2.push_back(pr.second); sort(vc2.begin(), vc2.end()); vc2.erase(unique(vc2.begin(), vc2.end()), vc2.end()); if(vc2.size()<=2) dfs(ch, v, vc2); } } ll ans; void solve(int root, int size){ if(size<=1) return; pair<int, vector<pair<int,int> > > pr=FindCentroid(root, size); int cent=pr.first; mp1.clear(); mp2.clear(); vector<int> vc0; dfs(cent, -1, vc0); for(auto p:mp1) ans+=p.second; auto calc=[&](){ ll ans1=0; for(auto p:mp1){ ans1+=p.second*p.second; int x=p.first.first, y=p.first.second; if(mp2.find(x)!=mp2.end()){ ans1+=p.second*mp2[x]*2; } if(mp2.find(y)!=mp2.end()){ ans1+=p.second*mp2[y]*2; } } ll sum=0; for(auto p:mp2) sum+=p.second; for(auto p:mp2) ans1+=p.second*(sum-p.second); return ans1; }; ll ans1=calc(); isRemoved[cent]=1; for(auto pr:tree[cent]){ int y=pr.first; if(!isRemoved[y]){ mp1.clear(); mp2.clear(); vector<int> vc0(1, pr.second); dfs(y, -1, vc0); ans1-=calc(); } } ans+=ans1/2; for(auto prr:pr.second){ if(!isRemoved[prr.first]) solve(prr.first, prr.second); } } int main() { int n, k; cin>>n>>k; for(int i=0; i<n-1; i++){ int u, v, c; scanf("%d %d %d", &u, &v, &c); u--; v--; tree[u].push_back({v, c}); tree[v].push_back({u, c}); } solve(0, n); cout<<ans<<endl; return 0; }