제출 #1350246

#제출 시각아이디문제언어결과실행 시간메모리
1350246simplemind_31LOSTIKS (INOI20_lostiks)C++20
23 / 100
72 ms28416 KiB
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll s,f,n,a,b,c,m,tiempo;
bool xd=true;
vector<vector<pair<ll,ll>>> graph;
vector<ll> val,pad,necesito,block,correspond;
vector<bool> visited;
vector<vector<ll>> dist;
void dfs1(ll node){
    for(auto u:graph[node]){
        if(u.first==pad[node])continue;
        val[u.first]=u.second;
        pad[u.first]=node;
        if(u.second!=-1){
            block.push_back(u.first);
            correspond[u.first]=block.size()-1;
        }
        dfs1(u.first);
    }
}
void dfs2(ll node){
    // para desbloquear cada uno necesito prerequisitos(necesito)
    // necesito desbloquear al padre y al actual
    if(visited[node])return;
    visited[node]=true;
    if(val[pad[node]]!=-1)necesito[node]|=1<<correspond[pad[node]];
    dfs2(pad[node]);
    necesito[node]|=necesito[pad[node]];
    if(val[node]!=-1){
        // necesito desbloquear val[node]
        if(val[val[node]]!=-1)necesito[node]|=1<<correspond[val[node]];
        dfs2(val[node]);
        necesito[node]|=necesito[val[node]];
        // si necesito bloq antes para desbloquear bloq->absurd;pero si no esta en el camino?
        /*if(necesito[node]&(1<<correspond[node])){
            xd=false;
            return;
        }*/
    }else{
        //nada, solo necesito del padre
    }
    for(auto u:graph[node]){
        if(u.first==pad[node])continue;
        dfs2(u.first);
    }
}
void dfs3(ll node,ll ind,ll ante){
    for(auto u:graph[node]){
        if(u.first==ante)continue;
        dist[ind][u.first]=dist[ind][node]+1;
        dfs3(u.first,ind,node);
    }
}
// minima cantidad para desboquear subset y terminar en block[i]?
// a que block puedo desbloquear si tengo actual?2^m*m
// tengo todos los requisitos para desbloquear el que tengo que desbloquear 
//dijkstra?
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin >> n >> s >> f;
    s--;f--;
    graph.resize(n+1);
    val.assign(n+1,-1);
    necesito.resize(n+1);
    visited.resize(n+1);
    correspond.assign(n+1,-1);
    pad.resize(n+1);
    for(ll i=1;i<n;i++){
        cin >> a >> b >> c;
        a--;b--;c--;
        if(a==f && c==-1)c=b;
        if(b==f && c==-1)c=a;
        graph[a].push_back({b,c});
        graph[b].push_back({a,c});
    }
    // añado uno extra
    graph[n].push_back({s,n});
    graph[s].push_back({n,n});
    pad[n]=n;
    val[n]=-1;
    dfs1(n);
    m=block.size();
    dfs2(n);
    //cout << val[s] << '\n';
    //for(ll i=0;i<m;i++)cout << block[i] << ' ';
    if(!xd){
        cout << -1;
        return 0;
    }
    /*for(ll i=0;i<n;i++){
        cout << i << ": ";
        for(ll j=0;j<m;j++){
            if(necesito[i]&(1<<j))cout << block[j] << ' ';
        }
        cout << '\n';
    }*/
    //cout << '\n';
    //calcular distancia desde cada block[j] a todos;
    dist.assign(m,vector<ll>(n+1));
    for(ll i=0;i<m;i++){
        dfs3(pad[block[i]],i,-1);
        //for(ll j=0;j<=n;j++)cout << dist[i][j] << ' ';
        //cout << endl;
    }
    vector<ll> res((1<<m)*m+m+1,1e18);
    // desbloquea subset x y termina en el nodo y
    // nuestra respuesta es 
    priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>> dij;
    // caso base, para desbloquear solo el start me cuesta 0
    // termino en padre del block[i];
    dij.push({0,(1<<0)*m+0});
    res[(1<<0)*m+0]=0;
    //cout << endl << endl;
    while(!dij.empty()){
        ll top=dij.top().second;
        ll nada=dij.top().first;
        dij.pop();
        if(res[top]<nada)continue;
        ll x=top/m,y=top%m;
        /*for(ll i=0;i<m;i++){
            if(x&(1<<i))cout << i << ' ';
        }
        cout << ": " << y << ' ';
        cout << res[top] << '\n';*/
        if(y==correspond[f]){
            cout << res[top];
            return 0;
        }
        for(ll j=0;j<m;j++){
            if(x&(1<<j))continue;
            //necesito necesito[block[j]] y tengo x
            if(necesito[block[j]]-(necesito[block[j]]&x))continue;
            // no era posible porwue necesitaba mas cosas
            // ir desde block[y] al val[block[j]] y de val[block[j]] al block[j];
            ll temp=dist[y][val[block[j]]]+dist[j][val[block[j]]]+res[top];
            if(temp<res[(x|(1<<j))*m+j]){
                res[(x|(1<<j))*m+j]=temp;
                //for(ll k=0;)
                /*for(ll i=0;i<m;i++){
                    if((x)&(1<<i))cout << block[i] << ' ';
                }*/
                //cout << ": " << block[y] << ' ' << block[j] << ' ';
                //cout << temp << '\n';
                dij.push({res[(x|(1<<j))*m+j],(x|(1<<j))*m+j});
            }
        }
    }
    cout << -1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...