제출 #720799

#제출 시각아이디문제언어결과실행 시간메모리
720799thimote75Evacuation plan (IZhO18_plan)C++14
0 / 100
328 ms29892 KiB

#include <bits/stdc++.h>

using namespace std;

#define bdata vector<bool>
#define idata vector<int>
#define graph vector<idata>
#define t_road pair<int, int>
#define rnext first
#define rcost second
#define t_roads vector<t_road>
#define w_graph vector<t_roads>
#define inf 1e9
#define di pair<int, int>
#define pq_dist set<di>
#define igrid vector<idata>

struct SegTree {
    idata tree;
    int size, start, height;

    void init (idata &res) {
        size = res.size();
        height = ceil(log2(size));
        start = 1 << height;

        tree.resize(start << 1, inf);
        for (int i = 0; i < size; i ++)
            tree[i + start] = res[i];
        
        for (int i = start - 1; i >= 1; i --)
            tree[i] = min(tree[2 * i], tree[2 * i + 1]);
    }
    int query (int l, int r) {
        l += start; r += start;
        int res = inf;

        while (l < r) {
            if ((l & 1) == 1) res = min(res, tree[l]);
            if ((r & 1) == 0) res = min(res, tree[r]);
        
            l = (l + 1) >> 1;
            r = (r - 1) >> 1;
        }

        if (l == r) res = min(res, tree[l]);

        return res;
    }
};

int nbNodes, nbRoads, nbNPP, nbQuery;
graph roads;
w_graph w_roads;

idata dist_npp;

idata dijkstra ( idata &start ) {
    idata res(nbNodes, inf);
    pq_dist node_queue;

    for (int u : start) {
        res[u] = 0;
        node_queue.insert({ 0, u });
    }

    while (node_queue.size() != 0) {
        di current = *(node_queue.begin());
        node_queue.erase(current);

        int dist = current.first;
        int node = current.second;
        if (dist != res[node]) continue ;

        for (t_road road : w_roads[node]) if (res[road.rnext] > dist + road.rcost) {
            di old = { res[road.rnext], road.rnext };
            
            res[road.rnext] = dist + road.rcost;
            node_queue.insert({ res[road.rnext], road.rnext });
        }
    }

    return res;
}

idata ufd_boss;
int boss (int x) {
    if (ufd_boss[x] != x)
        ufd_boss[x] = boss(ufd_boss[x]);
    return ufd_boss[x];
}
void compute_residual () {
    ufd_boss.resize(nbNodes);
    for (int i = 0; i < nbNodes; i ++)
        ufd_boss[i] = i;

    bdata visited(nbNodes);
    priority_queue<pair<pair<int, int>, pair<int, int>>> pq;

    for (int iN = 0; iN < nbNodes; iN ++) {
        for (t_road road : w_roads[iN]) {
            if (dist_npp[iN] < dist_npp[road.rnext]
             ||(dist_npp[iN] == dist_npp[road.rnext] && iN < road.rnext)) {
                pq.push({
                    { dist_npp[iN], dist_npp[road.rnext] },
                    { iN, road.rnext }
                });
            }
        }
    }

    while (pq.size() != 0) {
        auto mu = pq.top(); pq.pop();

        int a = mu.second.first;
        int b = mu.second.second;

        if (boss(a) == boss(b)) continue ;
        ufd_boss[boss(a)] = boss(b);

        roads[a].push_back(b);
        roads[b].push_back(a);
    }
}

const int MAX_N = 1e5 + 10;
const int MAX_K = 20;

idata depth;
idata parents;
idata subtree_size;
igrid parents_2k;

int dfs (int node, int parent, int l_depth) {
    depth       [node]    = l_depth;
    parents     [node]    = parent;
    parents_2k  [node][0] = parent;
    subtree_size[node]    = 1;

    for (int next : roads[node]) if (next != parent)
        subtree_size[node] += dfs(next, node, l_depth + 1);

    return subtree_size[node];
}

idata branch_main;
idata segtree_pos;
idata segtree_val;
int segtree_used = 0;
int idBranch = 0;
SegTree tree;
void create_branch (int node, int parent);
void hld (int node, int parent, int branch) {
    segtree_pos[node] = segtree_used ++;
    branch_main[node] = branch;

    segtree_val[segtree_pos[node]] = dist_npp[node];

    int mxSubtree = -1;
    int mxSubNode = -1;

    for (int next : roads[node]) if (next != parent && subtree_size[next] > mxSubtree) {
        mxSubtree = subtree_size[next];
        mxSubNode = next;
    }

    if (mxSubNode != -1)
        hld(mxSubNode, node, branch);

    for (int next : roads[node]) if (next != parent && next != mxSubNode)
        create_branch(next, node);
}
void create_branch (int node, int parent) {
    hld(node, parent, node);
}

int jump (int n, int k) {
    for (int i = 0; i < MAX_K; i ++) {
        if (((1 << i) & k) != 0) {
            n = parents_2k[n][i];
        }
    }

    return n;
}
int lca (int a, int b) {
    if (depth[a] > depth[b]) return lca(b, a);

    b = jump(b, depth[b] - depth[a]);
    if (a == b) return a;
    
    for (int i = 0; i < MAX_K; i ++) {
        if (parents_2k[a][i] == parents_2k[b][i]) continue ;

        a = parents_2k[a][i];
        b = parents_2k[b][i];
    }

    if (a == b) return a;
    return parents[a];
}
int _compute_min( int node, int parent ) {
    if (branch_main[node] == branch_main[parent])
        return tree.query( segtree_pos[parent], segtree_pos[node] );
    
    int next = parents[branch_main[node]];
    int quer = branch_main[node];

    return min(
        _compute_min(next, parent),
        tree.query( segtree_pos[quer], segtree_pos[node] )
    );
}
int compute_min (int a, int b) {
    int l = lca(a, b);

    return min( _compute_min(a, l), _compute_min(b, l) );
}

int main () {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> nbNodes >> nbRoads;
    w_roads.resize(nbNodes);
    roads  .resize(nbNodes);
    parents_2k.resize(nbNodes, idata(MAX_K));

    for (int iR = 0; iR < nbRoads; iR ++) {
        int a, b, c;
        cin >> a >> b >> c;

        a --;
        b --;
        w_roads[a].push_back({ b, c });
        w_roads[b].push_back({ a, c });
    }

    cin >> nbNPP;
    idata NPP_array(nbNPP);
    for (int iP = 0; iP < nbNPP; iP ++) {
        cin >> NPP_array[iP];
        NPP_array[iP] --;
    }
    
    dist_npp = dijkstra(NPP_array);
    compute_residual();

    depth  .resize(nbNodes);
    parents.resize(nbNodes);

    subtree_size.resize(nbNodes);

    for (int k = 0; k < MAX_K; k ++)
        for (int i = 0; i < nbNodes; i ++)
            parents_2k[i][k] = -1;
    
    dfs(0, -1, 0);

    for (int k = 0; k + 1 < MAX_K; k ++) {
        for (int i = 0; i < nbNodes; i ++) {
            if (parents_2k[i][k] == -1) continue ;

            parents_2k[i][k + 1] = parents_2k[parents_2k[i][k]][k];
        }
    }

    segtree_pos.resize(nbNodes);
    branch_main.resize(nbNodes);
    segtree_val.resize(nbNodes);
    create_branch(0, -1);

    /*tree.init(segtree_val);

    cin >> nbQuery;
    for (int iQ = 0; iQ < nbQuery; iQ ++) {
        int s, t;
        cin >> s >> t;
        s --; t --;

        cout << compute_min(s, t) << endl;
    }*/
}

컴파일 시 표준 에러 (stderr) 메시지

plan.cpp: In function 'std::vector<int> dijkstra(std::vector<int>&)':
plan.cpp:77:16: warning: variable 'old' set but not used [-Wunused-but-set-variable]
   77 |             di old = { res[road.rnext], road.rnext };
      |                ^~~
#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...