제출 #1347482

#제출 시각아이디문제언어결과실행 시간메모리
1347482notandyEvacuation plan (IZhO18_plan)C++20
0 / 100
226 ms56012 KiB
#include <bits/stdc++.h>

using namespace std;

#define mset(x,val) memset(x,val,sizeof(x))
#define allof(x) x.begin(), x.end()
#define fi first
#define se second

using ll = long long;
using vi = vector<int>;
using vii = vector<vector<int>>;
using vl = vector<long long>;
using vll = vector<vector<long long>>;
using vb = vector<bool>;
using vbb = vector<vector<bool>>;
using mii = map<int,int>;
using umii = unordered_map<int,int>;
using pii = pair<int,int>;
using pll = pair<long long,long long>;
using pli = pair<long long, int>;
using pil = pair<int, long long>;
#define __builtin_popcount __builtin_popcountll
#define BIT(x, i) (((x) >> (i)) & 1)
#define MASK(x) ((1ll << (x)))
#define debug(a, l, r) for (int _i = (l); _i <= (r); ++_i) cout << (a)[_i] << ' '; cout << '\n'; 

const int MOD = 1e9 + 7;
const int maxn = 1e5 + 5;

int n, m, q, k;

vector <vector<pil>> adj;
vector <vector<pil>> g;
vi sz, par, depth, heavy, head, pos;
vl dist, val;
vi k_rooms;
ll INF = 1e18;
int cur_pos=0;


struct DSU
{
    int n;
    vi par, sz;

    DSU () {}

    DSU (int _n) 
    {
        n = _n;
        par.resize(n+1);
        iota(allof(par), 0);
        sz.assign(n+1, 1);
    }

    int find(int x)
    {
        if (x == par[x]) return x;
        return par[x] = find(par[x]);
    }

    bool unite(int u, int v)
    {
        u = find(u);
        v = find(v);
        if (u == v) return 0;

        if (sz[u] < sz[v]) swap(u, v);
        par[v] = u;
        sz[u] += sz[v];
        return 1;
    }
};


vector <pair<ll, pii> > edges;


DSU dsu;

void kruskal()
{
    dsu = DSU(n);

    vector <pair<ll, pii>> new_edges;
    for (auto &e : edges)
    {
        new_edges.push_back({min(dist[e.se.fi], dist[e.se.se]), {e.se.fi, e.se.se}});
    }

    sort(allof(new_edges), greater<>());

    for (auto &e : new_edges)
    {
        int u = e.se.fi;
        int v = e.se.se;
        ll w = e.fi;
        if(dsu.unite(u, v))
        {
            adj[u].push_back({v, w});
            adj[v].push_back({u, w});
        }
    }
}




void dijkstra(int n)
{
    dist.assign(n+1, INF);

    priority_queue<pli, vector<pli>, greater<pli>> pq;
    for (int x : k_rooms) 
    {
        pq.push({0, x});
        dist[x]=0;
    }
    
    

    while(!pq.empty())
    {
        int u = pq.top().se;
        ll d = pq.top().fi;
        pq.pop();
        if (d != dist[u]) continue;

        for (auto &E : g[u])
        {
            int v = E.fi;
            ll w = E.se;

            if (dist[v] > dist[u] + w)
            {
                dist[v] = dist[u] + w;
                pq.push({dist[v], v});
            }
        }
    }
}




struct SegmentTree_Min
{
    vl vec;
    vl st;

    SegmentTree_Min(){}
    SegmentTree_Min(int n)
    {
        vec.resize(n+1);
        st.resize(4*n+5);
    }

    void build(int id, int l, int r)
    {
        if (l > r) return;
        if (l==r)
        {
            st[id] = vec[l];
            return;
        }

        int mid = (l + r ) >> 1;
        build(id<<1, l, mid);
        build(id<<1|1, mid+1, r);
        st[id] = min(st[id<<1], st[id<<1|1]);
    }

    ll query(int id, int l, int r, int ql, int qr)
    {
        if (r < ql || l > qr) return LLONG_MAX;
        if (ql <= l && r <= qr) return st[id];

        int mid = (l + r) >> 1;
        return min(query(id<<1, l, mid, ql, qr), query(id<<1|1, mid+1, r, ql, qr));
    }
};


int dfs(int u, int p)
{
    depth[u] = depth[p] + 1;
    par[u] = p;
    sz[u] =1;
    int mx_cnt = 0;

    for (auto &e: adj[u])
    {
        int v = e.fi;
        ll w = e.se;
        if (v == p) continue;
        val[v] = w;
        int s = dfs(v, u);
        
        sz[u] += s;

        if (s > mx_cnt)
        {
            mx_cnt = s;
            heavy[u]=v;
        }
    }

    return sz[u];
}

SegmentTree_Min ST;

void decompose(int u, int h)
{
    head[u] = h;
    pos[u] = ++cur_pos;
    ST.vec[cur_pos] = val[u];

    if (heavy[u]) decompose(heavy[u], h);

    for (auto &e : adj[u])
    {
        int v = e.fi;

        if (v == par[u] || v == heavy[u]) continue;
        decompose(v, v);
    }
}

ll query(int u, int v)
{
    ll res = LLONG_MAX;
    while(head[u] != head[v])
    {
        if (depth[head[u]] < depth[head[v]]) swap(u, v);
        res = min(res, ST.query(1, 1, n, pos[head[u]] +1, pos[u]));
        u = par[head[u]];
    }
    if (depth[u] > depth[v]) swap(u, v);
    return min(res, ST.query(1, 1, n, pos[u] + 1, pos[v]));
}


void Input()
{
    cin >> n >> m;
    adj.resize(n+1);
    g.resize(n+1);
    sz.resize(n+1), par.resize(n+1), depth.resize(n+1), heavy.resize(n+1, 0), head.resize(n+1), pos.resize(n+1);
    val.resize(n+1);

    for (int i=1 ;i<=m; ++i)
    {
        int u, v;
        ll w;
        cin>>u>>v>>w;
        edges.push_back({w, {u, v}});        
        g[u].push_back({v, w});
        g[v].push_back({u, w});

    }
    cin>>k;

    vb is_k(n+1,0);

    for (int i=1; i<=k; ++i) 
    {
        int x;
        cin>>x;
        k_rooms.push_back(x);
        is_k[x]=1;
    }

    
    
    dijkstra(n);
    kruskal();
    
    depth[0] = -1;
    dfs(1, 0);

    ST = SegmentTree_Min(n);
    
    decompose(1, 1);
    ST.build(1, 1, n);
    // debug(ST.vec, 1, n);

    cin>>q;
    while(q--)
    {
        int u, v;
        cin>>u>>v;
        if (is_k[u] || is_k[v]) cout<<0<<'\n';
        else cout<<query(u, v)<<'\n';
    }

}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    Input();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...