結果
| 問題 |
No.1002 Twotone
|
| コンテスト | |
| ユーザー |
pockyny
|
| 提出日時 | 2024-01-09 03:38:19 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,080 bytes |
| コンパイル時間 | 1,684 ms |
| コンパイル使用メモリ | 114,368 KB |
| 最終ジャッジ日時 | 2025-02-18 16:39:11 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 22 WA * 11 |
ソースコード
// https://onlinejudge.u-aizu.ac.jp/beta/review.html#OUPC2023Day2/8737708
#include <iostream>
#include <vector>
#include <map>
using namespace std;
struct CentroidDecomposition{
// 重心分解後の木の深さ
vector<int> rank;
// 部分木のサイズ
vector<int> sz;
// 元のグラフ
vector<vector<int>> g;
// 重心分解後の木におけるグラフの親
vector<int> par;
// 重心分解後の木におけるグラフの子 (あまり使わないらしいが一応持つ)
vector<vector<int>> child;
int n;
CentroidDecomposition(vector<vector<int>> &g) : n(g.size()), g(g), sz(g.size()), rank(g.size(), -1), par(g.size(), -1), child(g.size()) {
_build(0,-1);
}
// 部分木のサイズを計算
void calc_size(int v, int p) {
sz[v] = 1;
for(int to : g[v]) {
if(rank[to] == -1 && to != p) {
calc_size(to, v);
sz[v] += sz[to];
}
}
}
void _build(int v, int p) {
calc_size(v, -1);
int tot = sz[v];
bool ok = false;
int pp = -1;
// いま見ている部分木での重心を見つける
while(!ok) {
ok = true;
for(int to : g[v]) {
if(rank[to] == -1 && to != pp && 2 * sz[to] > tot) {
pp = v, v = to, ok = false;
break;
}
}
}
par[v] = p;
if(p != -1) {
child[p].push_back(v);
rank[v] = rank[p] + 1;
} else {
rank[v] = 0;
}
// 深さ優先でたどる
for(int to : g[v]) {
if(rank[to] == -1) {
_build(to, v);
}
}
}
};
typedef long long ll;
int main(){
int i,n,k; cin >> n >> k;
vector<vector<int>> g(n);
vector<vector<pair<int,int>>> G(n);
for(i=0;i<n - 1;i++){
int u,v,c; cin >> u >> v >> c;
u--; v--;
g[u].push_back(v);
g[v].push_back(u);
G[u].push_back({v,c});
G[v].push_back({u,c});
}
CentroidDecomposition cd(g);
// for(i=0;i<n;i++) cout << cd.rank[i] << " ";
// cout << "\n";
ll ans = 0;
for(i=0;i<n;i++){
int r = cd.rank[i];
vector<map<ll,ll>> vec;
vector<map<pair<ll,ll>,ll>> vec2;
// bool deb = i==0 && false;
auto dfs = [&](auto &&self,int v,int p,map<int,int> &mp,int id) -> void {
// if(deb){
// cout << "now = " << v << " " << mp.size() << " " << ans << "\n";
// for(auto p:mp) cout << p.first << " " << p.second << "\n";
// }
if(mp.size()>=3) return;
// i->v
if(mp.size()==2){
ans++;
auto it = mp.begin();
int c1 = (*it).first;
it++;
int c2 = (*it).first;
if(c1>c2) swap(c1,c2);
vec2[id][{c1,c2}]++;
}
if(mp.size()==1){
vec[id][(*mp.begin()).first]++;
}
for(auto e:G[v]){
if(e.first==p || cd.rank[e.first]<r) continue;
mp[e.second]++;
self(self,e.first,v,mp,id);
mp[e.second]--;
if(!mp[e.second]) mp.erase(e.second);
}
};
int id = 0;
for(auto e:G[i]){
if(cd.rank[e.first]<r) continue;
map<int,int> mp1;
mp1[e.second]++;
vec.resize(id + 1);
vec2.resize(id + 1);
dfs(dfs,e.first,i,mp1,id);
id++;
}
// cout << "i = " << i + 1 << " after_dfs " << ans << "\n";
// u->i->v;
ll val1 = 0,val2 = 0,val3 = 0,val4 = 0;
map<ll,ll> mp2;
int de = 0;
for(auto mp:vec){
ll sum3 = 0;
de++;
for(auto p:mp){
// cout << "de = " << de << " " << p.first << " " << p.second << "\n";
mp2[p.first] += p.second;
val1 += p.second;
sum3 += p.second;
val4 += p.second*p.second;
}
val3 += sum3*sum3;
}
for(auto p:mp2) val2 += p.second*p.second;
val1 *= val1;
ans += (val1 - val2 - val3 + val4)/2;
// cout << "i = " << i + 1 << " after_calc " << ans << "\n";
// cout << val1 << " " << val2 << " " << val3 << " " << val4 << " " << vec.size() << "\n";
for(int j=0;j<vec2.size();j++){
auto& mpp = vec2[j];
for(auto pp:mpp){
int c1 = pp.first.first,c2 = pp.first.second;
ll x1 = mp2.find(c1)!=mp2.end() ? mp2[c1] : 0;
ll x2 = mp2.find(c2)!=mp2.end() ? mp2[c2] : 0;
ll x3 = vec[j].find(c1)!=vec[j].end() ? vec[j][c1] : 0;
ll x4 = vec[j].find(c2)!=vec[j].end() ? vec[j][c2] : 0;
ans += pp.second*(x1 + x2 - x3 - x4);
}
}
}
cout << ans << "\n";
}
pockyny