zoukankan      html  css  js  c++  java
  • HDU3686 Traffic Real Time Query System 题解

    题目

    City C is really a nightmare of all drivers for its traffic jams. To solve the traffic problem, the mayor plans to build a RTQS (Real Time Query System) to monitor all traffic situations. City C is made up of N crossings and M roads, and each road connects two crossings. All roads are bidirectional. One of the important tasks of RTQS is to answer some queries about route-choice problem. Specifically, the task is to find the crossings which a driver MUST pass when he is driving from one given road to another given road.

    输入格式

    There are multiple test cases.
    For each test case:
    The first line contains two integers (N) and (M), representing the number of the crossings and roads.
    The next M lines describe the roads. In those M lines, the i th line (i starts from 1)contains two integers (X_i) and (Y_i), representing that road i connects crossing (X_i) and (Y_i) ((X_i≠Y_i)).
    The following line contains a single integer Q, representing the number of RTQs.
    Then Q lines follows, each describing a RTQ by two integers (S) and (T(S≠T)) meaning that a driver is now driving on the roads and he wants to reach roadt . It will be always at least one way from roads to roadt.
    The input ends with a line of “0 0”.
    Please note that: (0< N le 10000), (0 < M le 100000), (0 < Q le 10000), (0 < X_i),(Y_i le N), (0 < S,T le M)

    输出格式

    For each RTQ prints a line containing a single integer representing the number of crossings which the driver MUST pass.

    样例输入

    5 6
    1 2
    1 3
    2 3
    3 4
    4 5
    3 5
    2
    2 3
    2 4
    0 0
    

    样例输出

    0
    1
    

    题解

    题目大意:

    输出两条边之间必须经过的点

    这道题其实没有什么思维难度, 显然先缩点, 求lca即可.

    主要就是调起来很麻烦, 而且起点和终点不是点是边.

    tarjon缩点, 倍增求lca

    代码

    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int N = 1e4 + 5, M = 1e5 + 5, Lg = 25;
    int n, m, qn, tot, head[2][N << 1], top, sta[N], dfsc, dfn[N], low[N], dccCnt, root, bel[N], eb[M], fa[N << 1][Lg], dep[N << 1], id[N];
    bool cut[N], vis[N << 1];
    vector<int> dcc[N];
    struct Edge { int to, nxt, id; } edges[M << 2];
    inline void add(int type, int from, int to, int eid) {
        edges[++tot] = (Edge){to, head[type][from], eid}, head[type][from] = tot;
    }
    void tarjan(int x) {
        dfn[x] = low[x] = ++dfsc;
        sta[++top] = x;
        if (x == root && head[0][x] == 0)
            return dcc[++dccCnt].push_back(x);
        int son = 0;
        for (int i = head[0][x]; i; i = edges[i].nxt) {
            int y = edges[i].to;
            if (!dfn[y]) {
                tarjan(y);
                low[x] = min(low[x], low[y]);
                if (dfn[x] <= low[y]) {
                    son++;
                    if (x != root || son > 1) cut[x] = 1;
                    dccCnt++;
                    while(1){
                        int z = sta[top--];
                        dcc[dccCnt].push_back(z);
                        if (z == y) break;
                    }
                    dcc[dccCnt].push_back(x);
                }
            } else low[x] = min(low[x], dfn[y]);
        }
    }
    void dfs(int x, int fat, int depth) {
        vis[x] = 1, fa[x][0] = fat, dep[x] = depth;
        for (int i = 1; i <= 15; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
        for (int i = head[1][x]; i; i = edges[i].nxt) {
            int y = edges[i].to;
            if (vis[y]) continue;
            dfs(y, x, depth + 1);
        }
    }
    int lca(int x, int y) {
        if (dep[x] < dep[y]) swap(x, y);
        for (int i = 15; i >= 0; i--)
            if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
        if (x == y) return x;
        for (int i = 15; i >= 0; i--)
            if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
        return fa[x][0];
    }
    int main() {
        while (1) {
            scanf("%d%d", &n, &m);
            if (n == 0 && m == 0) break;
            tot = dfsc = dccCnt = top = 0;
            memset(head, 0, sizeof(head));
            memset(dfn, 0, sizeof(dfn));
            memset(low, 0, sizeof(low));
            memset(cut, 0, sizeof(cut));
            for (int x, y, i = 1; i <= m; i++) {
                scanf("%d%d", &x, &y);
                add(0, x, y, i), add(0, y, x, i);
            }
            for (int i = 1; i <= n; i++) dcc[i].clear();
            for (int i = 1; i <= n; i++)
                if (!dfn[i]) tarjan(root = i);
            int now = dccCnt;
            for (int i = 1; i <= n; i++)
                if (cut[i]) id[i] = ++now;
            for (int i = 1; i <= dccCnt; i++) {
                for (int j = 0; j < dcc[i].size(); j++) {
                    int x = dcc[i][j];
                    if (cut[x]) add(1, id[x], i, 0), add(1, i, id[x], 0);
                    bel[x] = i;
                }
                for (int j = 0; j < dcc[i].size(); j++)
                    for (int k = head[0][dcc[i][j]]; k; k = edges[k].nxt) if (bel[edges[k].to] == i) eb[edges[k].id] = i;
            }
            memset(dep, 0, sizeof(dep));
            memset(fa, 0, sizeof(fa));
            memset(vis, 0, sizeof(vis));
            for (int i = 1; i <= now; i++) if (!vis[i]) dfs(i, 0, 1);
            scanf("%d", &qn);
            for (int x, y; qn--;) {
                scanf("%d%d", &x, &y);
                x = eb[x], y = eb[y];
                if (x == y) puts("0");
                else printf("%d
    ", (dep[x] + dep[y] - 2 * dep[lca(x, y)]) / 2);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Atitti 图像处理 图像混合 图像叠加 blend 原理与实现
    Atitit Gaussian Blur 高斯模糊 的原理and实现and 用途
    Atitit 图像处理 灰度图片 灰度化的原理与实现
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    Atitit 实现java的linq 以及与stream api的比较
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库
    Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结
    Atitit apache 和guava的反射工具
    atitit。企业的价值观 员工第一 vs 客户第一.docx
  • 原文地址:https://www.cnblogs.com/youxam/p/hdu3686.html
Copyright © 2011-2022 走看看