結果

問題 No.1002 Twotone
ユーザー IKyoproIKyopro
提出日時 2020-03-29 17:01:46
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 4,011 bytes
コンパイル時間 3,259 ms
コンパイル使用メモリ 242,264 KB
実行使用メモリ 90,248 KB
最終ジャッジ日時 2024-06-10 19:21:19
合計ジャッジ時間 29,381 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 2 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 WA -
testcase_04 WA -
testcase_05 WA -
testcase_06 AC 2 ms
6,944 KB
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 AC 2 ms
6,944 KB
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 WA -
testcase_16 WA -
testcase_17 WA -
testcase_18 AC 2 ms
6,940 KB
testcase_19 WA -
testcase_20 WA -
testcase_21 WA -
testcase_22 WA -
testcase_23 WA -
testcase_24 WA -
testcase_25 WA -
testcase_26 AC 2 ms
6,940 KB
testcase_27 AC 157 ms
60,804 KB
testcase_28 AC 301 ms
90,248 KB
testcase_29 AC 261 ms
90,240 KB
testcase_30 AC 2 ms
6,944 KB
testcase_31 AC 242 ms
89,888 KB
testcase_32 AC 305 ms
89,976 KB
testcase_33 AC 260 ms
89,852 KB
testcase_34 WA -
権限があれば一括ダウンロードができます

ソースコード

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);
            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";
}
0