Bzoj3832: [poi2014] rally (topology sort heap)

Posted by cainy1982 on Tue, 03 Dec 2019 06:02:59 +0100

meaning of the title

Title Link

Sol

The most intuitive idea is to find the longest way after deleting each point. Let's consider how to find this thing

Set \ (f[i] \) to represent the longest path length ending with \ (I \), and \ (g[i] \) to represent the longest path length starting with \ (I \)

According to the nature of DAG, it is obvious that when we delete a point, the whole set will be divided into two parts: the topological order is less than / greater than the current point

Then the longest path at this time can be obtained by calculating \ (f(u) + f(v) +1 \) of the edge \ ((u, v) \) connecting two sets

In this way, we can directly maintain the edge set. When we count the answers of each point, we first delete the contribution statistical answers of the input edge, and then add the contribution of the output edge

Obviously, the line tree can be maintained, in fact, the heap can also be maintained. See the code for details (copied from yyb big guy)

#include<bits/stdc++.h>
#define chmax(x, y) (x = (x > y ? x : y))
#define chmin(x, y) (x = (x < y ? x : y))
using namespace std;
const int MAXN = 1e6 + 10, INF = 1e9 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M, a1 = INF, a2;
class MyPriorityQueue {
    public: 
        priority_queue<int> q1, q2;
        void push(int x) {
            q1.push(x);
        }
        int pop(int x) {
            q2.push(x);
        }
        bool empty() {
            while(!q2.empty() && (q1.top() == q2.top())) q1.pop(), q2.pop();
            return q1.size() == 0;
        }
        int top() {
            return empty() ? INF : q1.top();
        }   
};
MyPriorityQueue Q;
struct Graph {
    vector<int> v[MAXN];
    int f[MAXN], inder[MAXN], id[MAXN], tot;
    Graph() {
        tot = 0;
    }
    void AddEdge(int x, int y) {
        v[x].push_back(y); inder[y]++;
    }
    void Topsort() {
        queue<int> q;
        for(int i = 1; i <= N; i++) if(!inder[i]) q.push(i);
        while(!q.empty()) {
            int p = q.front(); q.pop(); id[++tot] = p;
            for(int i = 0; i < v[p].size(); i++) {
                int to = v[p][i]; chmax(f[to], f[p] + 1);
                if(!(--inder[to])) q.push(to);
            }
        }
    }
};
Graph Gs, Gt;
int main() {
    N = read(); M = read();
    for(int i = 1; i <= M; i++) {
        int x = read(), y = read();
        Gs.AddEdge(x, y); Gt.AddEdge(y, x);
    }
    Gs.Topsort(); Gt.Topsort();
    for(int i = 1; i <= N; i++) Q.push(Gt.f[i]);
    for(int t = 1; t <= N; t++) {
        int x = Gs.id[t]; Q.pop(Gt.f[x]);
        for(int i = 0; i < Gt.v[x].size(); i++) {
            int to = Gt.v[x][i];
            Q.pop(Gs.f[to] + Gt.f[x] + 1);
        }
        int now = Q.top(); Q.push(Gs.f[x]);
        if(now < a1) a1 = now, a2 = x;
        for(int i = 0; i < Gs.v[x].size(); i++) {
            int to = Gs.v[x][i];
            Q.push(Gs.f[x] + Gt.f[to] + 1);
        }
    }
    printf("%d %d\n", a2, a1);
    return 0;
}

Topics: C++ less