結果
| 問題 |
No.1002 Twotone
|
| コンテスト | |
| ユーザー |
IKyopro
|
| 提出日時 | 2020-03-29 17:01:46 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,011 bytes |
| コンパイル時間 | 3,170 ms |
| コンパイル使用メモリ | 231,712 KB |
| 最終ジャッジ日時 | 2025-01-09 10:47:05 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 12 WA * 21 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T, class U> using Pa = pair<T, U>;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
struct edge{
int to;
ll dist,col;
edge(int to,ll dist,ll col):to(to),dist(dist),col(col){};
};
class CentroidDecomposition{
public:
int N;
vvec<edge> g;
vec<int> size;
vec<int> used;
CentroidDecomposition(int N,vvec<edge> tree): N(N),g(tree){
size = used = vec<int>(N,0);
}
int calc_size(int cur,int par){
int c = 1;
for(auto& x:g[cur]){
if(x.to==par || used[x.to]) continue;
c += calc_size(x.to,cur);
}
return size[cur] = c;
}
//tは連結成分の大きさ
//cur以下のうち、削除して残る最大の部分木の大きさを返す
Pa<int,int> search_centroid(int cur,int par,int cmp_size){
Pa<int,int> res = {1e9,-1};
int s = 1,ma = 0;
for(auto& x:g[cur]){
if(x.to==par || used[x.to]) continue;
res = min(res,search_centroid(x.to,cur,cmp_size));
ma = max(ma,size[x.to]);
s += size[x.to];
}
//子と親の部分木の大きい方
ma = max(ma,cmp_size-s);
res = min(res,{ma,cur});
return res;
}
void dfs(int cur,int par,ll d){
for(auto& e:g[cur]) if(e.to!=par && !used[e.to]){
dfs(e.to,cur,d+e.dist);
}
}
int build(int v){
calc_size(v,-1);
int centroid = search_centroid(v,-1,size[v]).second;
used[centroid] = true;
return centroid;
}
void disable(int v){used[v] = true;}
bool is_alive(int v){return !used[v];}
};
int main(){
cin.tie(0);
ios::sync_with_stdio(false);
int N,K;
cin >> N >> K;
vvec<edge> g(N);
for(int i=0;i<N-1;i++){
int a,b;
ll c;
cin >> a >> b >> c;
a--; b--;
g[a].push_back({b,1,c});
g[b].push_back({a,1,c});
}
CentroidDecomposition CD(N,g);
queue<int> Q;
ll ans = 0;
Q.push(0);
while(!Q.empty()){
int c = CD.build(Q.front()); Q.pop();
map<ll,ll> S,Sp;
map<Pa<ll,ll>,ll> D;
int n = g[c].size();
vec<map<ll,ll>> Sv(n),Spv(n);
vec<map<Pa<ll,ll>,ll>> Dv(n);
ll cnt1 = 0;
auto dfs = [&](auto&& self,int cur,int par,int id,int c1=-1,int c2=-1)->void{
assert(c1!=c2);
if(c1!=-1 && c2==-1){
S[c1]++;
Sv[id][c1]++;
cnt1++;
}
if(c1!=-1 && c2!=-1){
D[minmax({c1,c2})]++;
Sp[c1]++;
Sp[c2]++;
Dv[id][minmax({c1,c2})]++;
Spv[id][c1]++;
Spv[id][c2]++;
ans++;
}
for(auto& e:g[cur]) if(e.to!=par && CD.is_alive(e.to)){
if(c1==-1) self(self,e.to,cur,id,e.col,c2);
else if(c2==-1){
if(c1!=e.col) self(self,e.to,cur,id,c1,e.col);
else self(self,e.to,cur,id,c1,c2);
}else{
if(c1==e.col || c2==e.col) self(self,e.to,cur,id,c1,c2);
}
}
};
for(int i=0;i<n;i++){
edge& e = g[c][i];
if(CD.is_alive(e.to)){
dfs(dfs,e.to,-1,i,e.col,-1);
Q.push(e.to);
}
}
ll res1 = 0,res2 = 0,res3 = 0;
for(int i=0;i<n;i++){
ll sum = 0;
for(auto& x:Sv[i]) sum += x.second;
for(auto& x:Sv[i]){
res1 += x.second*(cnt1-S[x.first]-(sum-x.second));
res2 += x.second*(Sp[x.first]-Spv[i][x.first]);
}
for(auto& x:Dv[i]){
res3 += x.second*(D[x.first]-x.second);
}
}
ans += res1/2+res2/4+res3/2;
}
cout << ans << "\n";
}
IKyopro