結果

問題 No.1002 Twotone
ユーザー IKyoproIKyopro
提出日時 2020-03-29 17:26:08
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 2,550 ms / 5,000 ms
コード長 4,200 bytes
コンパイル時間 2,909 ms
コンパイル使用メモリ 240,948 KB
実行使用メモリ 84,460 KB
最終ジャッジ日時 2023-08-30 19:52:37
合計ジャッジ時間 30,156 ms
ジャッジサーバーID
(参考情報)
judge13 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,380 KB
testcase_01 AC 1 ms
4,380 KB
testcase_02 AC 2 ms
4,376 KB
testcase_03 AC 626 ms
42,876 KB
testcase_04 AC 835 ms
54,492 KB
testcase_05 AC 832 ms
54,592 KB
testcase_06 AC 1 ms
4,376 KB
testcase_07 AC 436 ms
34,408 KB
testcase_08 AC 786 ms
54,808 KB
testcase_09 AC 790 ms
54,476 KB
testcase_10 AC 2 ms
4,380 KB
testcase_11 AC 972 ms
43,044 KB
testcase_12 AC 1,312 ms
54,856 KB
testcase_13 AC 1,326 ms
54,804 KB
testcase_14 AC 2 ms
4,376 KB
testcase_15 AC 671 ms
32,492 KB
testcase_16 AC 1,386 ms
54,756 KB
testcase_17 AC 1,397 ms
54,644 KB
testcase_18 AC 2 ms
4,376 KB
testcase_19 AC 1,373 ms
51,348 KB
testcase_20 AC 1,626 ms
63,920 KB
testcase_21 AC 1,616 ms
63,320 KB
testcase_22 AC 2 ms
4,376 KB
testcase_23 AC 1,164 ms
43,700 KB
testcase_24 AC 2,022 ms
67,876 KB
testcase_25 AC 2,124 ms
67,708 KB
testcase_26 AC 1 ms
4,380 KB
testcase_27 AC 147 ms
52,368 KB
testcase_28 AC 277 ms
77,544 KB
testcase_29 AC 232 ms
78,292 KB
testcase_30 AC 2 ms
4,380 KB
testcase_31 AC 223 ms
77,856 KB
testcase_32 AC 290 ms
77,124 KB
testcase_33 AC 233 ms
78,852 KB
testcase_34 AC 2,550 ms
84,460 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),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);
//            cerr << "centroid : " << c << " cur : " << cur << "\n";
            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(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);
            }
        }
//        cerr << c << " " << ans << " " << res1 << " " << res2 << " " << res3 << "\n";
        ans += res1/2+res2+res3/2;
    }
    cout << ans << "\n";
}
0