Submission #1279687

#TimeUsernameProblemLanguageResultExecution timeMemory
1279687daveleLOSTIKS (INOI20_lostiks)C++20
100 / 100
1376 ms608176 KiB
// nhan xet quan trong cho bai nay:
//co the thay m =20 da goi y bai nay la dp bitmask, van de o day la co toi n dinh can luu trang thai
//mot cach giam so luong trang thai hieu qua do la loai bo cac trang thai khong quan trong
//noi cach khac, voi moi canh bi cam ta chi can quan tam va danh dau cac dinh dau mut cua canh nay
//
//No la ki thuat khong cu, co dieu da bi lang quen
//
//Ngoai ra ta co 1 chung minh bo tro nhu sau
//vi no la cay, nen chi ton tai duy nhat 1 duong di tu u den v -> cac duong di kieu gi thi kieu cung di qua dong nay
//
//suy ra voi cac bai mo khoa -> phai lay chia truoc roi tu chia di den o khoa
//ngoai ra nho no la cay ta cung co the de dang kiem tra xem doan duong bat buoc phai qua nhung loai khoa nao
//Het roi!
//
//A mot nhan xet lam giam so chieu
//tu s ta chi di den dinh gan hon (no khong dung voi moi trang thai dp nhung se dung voi ket qua toi uu)

#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
#define fi first
#define se second
#define vi vector <int>
#define pq priority_queue
#define MASK(i) (1ll<<(i))
#define BIT(x, i) (((x) >> (i)) & 1)
#define x0 ___x0
#define y0 ___y0
#define div   ___div
#define next   ___next
#define prev   ___prev
#define left   ___left
#define right   ___right
#define pos pisosi
#define pb push_back
#define pf push_front
using namespace std;

//const int mod = ;
//void add (int &a, const int&b){
//    a+=b;
//    if (a>=mod) a-=mod;
//}
//
//void sub (int&a, const int&b){
//    a-=b;
//    if (a<0) a+=mod;
//}
//
//void mul (int&a, const int&b){
//    a*=b;
//    a%=mod;
//}

template<class X, class Y>
    bool minimize(X &x, const Y&y){
        if (x<=y) return false;
        else{
            x = y;
            return true;
        }
    }
template<class X, class Y>
    bool maximize (X &x, const Y&y){
        if (x>=y) return false;
        else{
            x = y;
            return true;
        }
    }

/////////////////////////////////////////////////////////////////////////////////

//// dang nhap ham
//#ifndef davele
//
//#endif // davele
//
//// chay thu ham main:
//
//#ifdef davele
//
//#endif // davele

////////////////////////////////////////////////////////////////////////////
//const int lim = , limit = , inf = ;
const string name = "treemaze";
const int lim = 1100000, limit = lim+5, inf = 1e18;

int n, m, s, t;
int key[limit];
pii edge[limit];
int maskval[limit];
vector <pii> adj[limit];
int pos[limit], numlca, dslca[2*limit];
int rmq[2*limit][21];
int dp[limit][21];
int st[limit], en[limit], cntdfs;
int opt[limit];

int h[limit], summask[limit];

void dfs (int u, int pre){
    st[u]=++cntdfs;
    pos[u] = ++numlca;
    dslca[numlca] = u;
    for (pii x:adj[u]){
        int v = x.fi, id = x.se;
        if (v==pre) continue;
        h[v] = h[u]+1;
        summask[v] = summask[u] + maskval[id];
        dfs(v, u);
        dslca[++numlca] = u;
    }
    en[u] = cntdfs;
}

int getmin (int u, int v){
    if (h[u]<h[v]) return u;
    return v;
}

int lca (int u, int v){
    int l = pos[u], r = pos[v];
    if (l>r) swap(l, r);
    int tm = 31-__builtin_clz(r-l+1);
    return getmin (rmq[l][tm], rmq[r-MASK(tm)+1][tm]);
}

int getbit (int u, int v){
    return summask[u]^summask[v];
}

int dist (int u, int v){
    int LCA = lca(u, v);
    return h[u]+h[v]-2*h[LCA];
}

bool parchild (int pare, int chil){
    return (pare&chil)==chil;
}

void process(){
    dfs (1, 1);
    for (int i=1; i<=numlca; i++) rmq[i][0] = dslca[i];
    for (int i=1; i<=20; i++){
        for (int j=1; j+MASK(i)-1<=numlca; j++){
            rmq[j][i] = getmin (rmq[j][i-1], rmq[j+MASK(i-1)][i-1]);
        }
    }
    for (int i=0; i<m; i++){
        int u = edge[i].fi, v = edge[i].se;
        if (h[u]<h[v]) swap(u, v);
        if (st[s]>=st[u] && st[s]<=en[u]) opt[i] = u;
        else opt[i] = v;
    }
    // xu ly truong hop di mot mach tu s den t
    if (getbit(s,t)==0){
        cout<<dist(s, t);
        return;
    }
    //
    int ALLMASK = MASK(m)-1;
    for (int i=1; i<=ALLMASK; i++) for (int j=0; j<m; j++)
        dp[i][j] = inf;
    // xu ly truong hop 1 bit
    for (int i=0; i<m; i++){
        int tmp = key[i];
        //
        if (getbit(s, tmp)==0 && getbit(tmp, opt[i])==0){
            minimize (dp[MASK(i)][i], dist(s,tmp)+dist(tmp, opt[i]));
        }
//        cerr<<getbit(s, tmp)<<"\n";
//        cerr<<i<<" "<<tmp<<" "<<fiu<<" "<<seu<<" "<<dp[MASK(i)][i][0]<<" "<<dp[MASK(i)][i][1]<<"\n";
    }
    int ret = inf;
    //
    for (int mask=1; mask<=ALLMASK; mask++){
        for (int i=0; i<m; i++) if (MASK(i)&mask){
                if (dp[mask][i]==inf) continue;
                int u = opt[i];
//                cerr<<mask<<" "<<i<<" "<<j<<" "<<u<<" "<<dp[mask][i][j]<<"\n";
                if (parchild(mask, getbit(u, t))){
//                    cerr<<u<<" "<<mask<<" "<<dp[mask][i][j]<<" "<<dist(u, t)<<"\n";
                    minimize (ret, dp[mask][i]+dist(u, t));
                }
                //
                for (int z=0; z<m; z++) if (BIT(mask, z)==0){
                    int khoa = key[z];
                    int tmp = getbit(u, khoa);
                    if (!parchild(mask, tmp)) continue;
                    int newmask = mask^MASK(z);
                    if (parchild(mask, getbit(khoa, opt[z]))){
                        minimize (dp[newmask][z], dp[mask][i]+dist(u, khoa)+dist(khoa, opt[z]));
                    }
            }
        }
    }
    if (ret==inf) cout<<"-1";
    else cout<<ret;
}

signed main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //
//    if (fopen((name+".inp").c_str(), "r")){
//        freopen ((name+".inp").c_str(), "r", stdin);
//        freopen ((name+".out").c_str(), "w", stdout);
//    }
    //
    cin>>n>>s>>t;
    m = 0;
    for (int i=1; i<n; i++){
        int u, v, H;
        cin>>u>>v>>H;
        if (H>0){
            key[m] = H;
            edge[m] = {u, v};
            maskval[i] = MASK(m);
            m++;
        }
        else{
            maskval[i] = 0;
        }
        adj[u].pb({v, i});
        adj[v].pb({u, i});
    }
    process();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...