結果

問題 No.1002 Twotone
ユーザー IKyoproIKyopro
提出日時 2020-03-29 17:24:07
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 4,198 bytes
コンパイル時間 2,958 ms
コンパイル使用メモリ 241,696 KB
実行使用メモリ 54,580 KB
最終ジャッジ日時 2023-08-30 19:51:49
合計ジャッジ時間 20,618 ms
ジャッジサーバーID
(参考情報)
judge13 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
8,760 KB
testcase_01 AC 1 ms
4,380 KB
testcase_02 AC 1 ms
4,380 KB
testcase_03 AC 2,494 ms
42,780 KB
testcase_04 AC 3,293 ms
54,580 KB
testcase_05 AC 3,281 ms
54,476 KB
testcase_06 AC 3 ms
4,380 KB
testcase_07 TLE -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
testcase_33 -- -
testcase_34 -- -
権限があれば一括ダウンロードができます

ソースコード

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