結果

問題 No.1002 Twotone
ユーザー IKyoproIKyopro
提出日時 2020-03-29 17:28:09
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 2,071 ms / 5,000 ms
コード長 3,973 bytes
コンパイル時間 2,949 ms
コンパイル使用メモリ 240,632 KB
実行使用メモリ 78,136 KB
最終ジャッジ日時 2023-08-30 19:53:20
合計ジャッジ時間 29,489 ms
ジャッジサーバーID
(参考情報)
judge14 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,376 KB
testcase_01 AC 2 ms
4,380 KB
testcase_02 AC 1 ms
4,376 KB
testcase_03 AC 607 ms
42,832 KB
testcase_04 AC 804 ms
54,584 KB
testcase_05 AC 784 ms
54,596 KB
testcase_06 AC 2 ms
4,376 KB
testcase_07 AC 423 ms
34,404 KB
testcase_08 AC 762 ms
54,660 KB
testcase_09 AC 760 ms
54,836 KB
testcase_10 AC 2 ms
4,380 KB
testcase_11 AC 970 ms
43,080 KB
testcase_12 AC 1,326 ms
54,648 KB
testcase_13 AC 1,356 ms
54,732 KB
testcase_14 AC 2 ms
4,376 KB
testcase_15 AC 693 ms
32,560 KB
testcase_16 AC 1,386 ms
54,800 KB
testcase_17 AC 1,361 ms
54,728 KB
testcase_18 AC 1 ms
4,376 KB
testcase_19 AC 1,380 ms
51,588 KB
testcase_20 AC 1,692 ms
63,860 KB
testcase_21 AC 1,665 ms
63,328 KB
testcase_22 AC 2 ms
4,380 KB
testcase_23 AC 1,129 ms
43,780 KB
testcase_24 AC 2,033 ms
67,812 KB
testcase_25 AC 2,071 ms
67,796 KB
testcase_26 AC 1 ms
4,376 KB
testcase_27 AC 139 ms
47,264 KB
testcase_28 AC 261 ms
68,064 KB
testcase_29 AC 222 ms
69,188 KB
testcase_30 AC 1 ms
4,380 KB
testcase_31 AC 214 ms
67,664 KB
testcase_32 AC 275 ms
69,200 KB
testcase_33 AC 224 ms
67,984 KB
testcase_34 AC 1,989 ms
78,136 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#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);
        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})]++;
                ans++;
            }
            for(auto& e:g[cur]) if(e.to!=par && CD.is_alive(e.to)){
                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));
            }
            for(auto& x:Dv[i]){
                res2 += x.second*(S[x.first.first]-(sum-Sv[i][x.first.first]));
                res2 += x.second*(S[x.first.second]-(sum-Sv[i][x.first.second]));
                res3 += x.second*(D[x.first]-x.second);
            }
        }
        ans += res1/2+res2+res3/2;
    }
    cout << ans << "\n";
}
0