結果

問題 No.1002 Twotone
ユーザー IKyoproIKyopro
提出日時 2020-03-29 17:28:09
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 1,944 ms / 5,000 ms
コード長 3,973 bytes
コンパイル時間 3,205 ms
コンパイル使用メモリ 242,700 KB
実行使用メモリ 78,208 KB
最終ジャッジ日時 2024-06-10 19:24:56
合計ジャッジ時間 27,499 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,816 KB
testcase_01 AC 2 ms
6,944 KB
testcase_02 AC 1 ms
6,940 KB
testcase_03 AC 523 ms
42,820 KB
testcase_04 AC 757 ms
54,680 KB
testcase_05 AC 744 ms
54,648 KB
testcase_06 AC 2 ms
6,944 KB
testcase_07 AC 349 ms
34,644 KB
testcase_08 AC 799 ms
54,852 KB
testcase_09 AC 747 ms
54,788 KB
testcase_10 AC 2 ms
6,948 KB
testcase_11 AC 866 ms
43,116 KB
testcase_12 AC 1,292 ms
54,888 KB
testcase_13 AC 1,290 ms
54,884 KB
testcase_14 AC 2 ms
6,940 KB
testcase_15 AC 542 ms
32,860 KB
testcase_16 AC 1,331 ms
54,776 KB
testcase_17 AC 1,333 ms
54,828 KB
testcase_18 AC 2 ms
6,940 KB
testcase_19 AC 1,249 ms
51,540 KB
testcase_20 AC 1,490 ms
64,120 KB
testcase_21 AC 1,436 ms
63,612 KB
testcase_22 AC 2 ms
6,940 KB
testcase_23 AC 993 ms
43,572 KB
testcase_24 AC 1,890 ms
67,836 KB
testcase_25 AC 1,944 ms
67,960 KB
testcase_26 AC 2 ms
6,940 KB
testcase_27 AC 130 ms
46,456 KB
testcase_28 AC 249 ms
68,128 KB
testcase_29 AC 216 ms
68,348 KB
testcase_30 AC 2 ms
6,940 KB
testcase_31 AC 203 ms
67,568 KB
testcase_32 AC 257 ms
68,332 KB
testcase_33 AC 217 ms
68,136 KB
testcase_34 AC 1,846 ms
78,208 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