ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HDU3686 Traffic Real Time Query【缩点+lca】

2020-05-06 16:11:29  阅读:284  来源: 互联网

标签:Real 缩点 int 割点 ++ edge lca roads now


题目

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.

Input

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<=10000, 0<M<=100000, 0<Q<=10000, 0<X i,Y i<=N, 0<S,T<=M

Output

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

Sample Input

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

Sample Output

0 1

分析

大概的题目意思就是给个无向图,问从a到b的路径中有几个点必须经过。

思路:根据题意,很容易就可以想到这个题就是求a到b的路径上割点的个数。然后就可以开始缩点了。把边缩成一个点,因为每条边有且仅属于一个联通块中,然后对割点和它相邻的块建边,这样就构造了一棵树。询问a边和b边,只需要找出它们分别属于哪个块中就行,所以问题转化成了一棵树中,有些点标记了是割点,现在询问两个不为割点的点路径上有多少个割点。

这样就很容易做了,以任意一个点为树根,求出每个点到树根路径上有多少个割点,然后对于询问的两个点求一次LCA就可以求出结果了,有点小细节不多说,自己画个图就清楚了。

注意:缩点后树的点数可能是2n个。

代码

#include<cstdio>
#include <vector>
#include <algorithm>
using namespace std;
 
const int maxn = 10000 + 10;  
const int maxm = 100000 + 10;
 
struct Edge {
    int u, to, next, vis, id;
}edge[maxm<<1];
 
int head[maxn<<1], dfn[maxn<<1], low[maxn], st[maxm], iscut[maxn], subnet[maxn], bian[maxm];
int E, time, top, btot;
vector<int> belo[maxn];
void newedge(int u, int to) {
    edge[E].u = u;
    edge[E].to = to;
    edge[E].next = head[u];
    edge[E].vis = 0;
    head[u] = E++;
}
 
void init(int n) {
    for(int i = 0;i <= n; i++) {
        head[i] = -1;
        dfn[i] = iscut[i] = subnet[i] = 0;
        belo[i].clear();
    }
    E = time = top = btot = 0;
}
 
void dfs(int u) {
    dfn[u] = low[u] = ++time;
    for(int i = head[u];i != -1;i = edge[i].next) {
        if(edge[i].vis) continue;
        edge[i].vis = edge[i^1].vis = 1;
        int to = edge[i].to;
        st[++top] = i;
        if(!dfn[to]) {
            dfs(to);
            low[u] = min(low[u], low[to]);
            if(low[to] >= dfn[u]) {
                subnet[u]++;
                iscut[u] = 1;
                btot++;
                do {
                    int now = st[top--];
                    belo[edge[now].u].push_back(btot);
                    belo[edge[now].to].push_back(btot);
                    bian[edge[now].id] = btot;
                    to = edge[now].u;
                }while(to != u);
            }
        }
        else
            low[u] = min(low[u], low[to]);
    }
}
 
int B[maxn<<2], F[maxn<<2], d[maxn<<2][20], pos[maxn<<2], tot, dep[maxn<<1];
bool treecut[maxn<<1];  
void RMQ1(int n) {
    for(int i = 1;i <= n; i++)  d[i][0] = B[i];
    for(int j = 1;(1<<j) <= n; j++)
        for(int i = 1;i + j - 1 <= n; i++)
            d[i][j] = min(d[i][j-1], d[i + (1<<(j-1))][j-1]);
}
 
int RMQ(int L, int R) {
    int k = 0;
    while((1<<(k+1)) <= R-L+1)  k++;
    return min(d[L][k], d[R-(1<<k)+1][k] );
}
 
int lca(int a, int b) {
    if(pos[a] > pos[b])   swap(a, b);
    int ans = RMQ(pos[a], pos[b]);
    return F[ans];
}
 
// 搜树来构造RMQ LCA
void DFS(int u) {
    dfn[u] = ++time;
    B[++tot] = dfn[u];
    F[time] = u;
    pos[u] = tot;
    for(int i = head[u];i != -1;i = edge[i].next){
        int to = edge[i].to;
        if(!dfn[to]) {
            if(treecut[u])
                dep[to] = dep[u] + 1;
            else
                dep[to] = dep[u];
            DFS(to);
            B[++tot] = dfn[u];
        }
    }
}
 
void solve(int n) {
    for(int i = 0;i <= n; i++)  {
        dfn[i] = 0;
    }
    time = tot = 0;
    for(int i = 1;i <= n; i++) if(!dfn[i]) {
        dep[i] = 0;
        DFS(i);
    }
    RMQ1(tot);
    int m, u, to;
    scanf("%d", &m);
    while(m--) {
        scanf("%d%d", &u, &to);
        u = bian[u]; to = bian[to];
        if(u < 0 || to < 0) {
            printf("0\n"); continue;
        }
        int LCA = lca(u, to);
        if(u == LCA)
            printf("%d\n", dep[to] - dep[u] - treecut[u]);
        else if(to == LCA)
            printf("%d\n", dep[u] - dep[to] - treecut[to]);
        else
            printf("%d\n", dep[u] + dep[to] - 2*dep[LCA] - treecut[LCA]);
    }
}
 
int main() {
    int n, m, u, to;
    while(scanf("%d%d", &n, &m) != -1 && n){
        init(n);
        for(int i = 1;i <= m; i++) {
            scanf("%d%d", &u, &to);
            edge[E].id = i;
            newedge(u, to);
            edge[E].id = i;
            newedge(to, u);
        }
 
        for(int i = 1;i <= n;i ++) if(!dfn[i]) {
            dfs(i);
            subnet[i]--;
            if(subnet[i] <= 0)  iscut[i] = 0;
        }
        int ditot = btot;
        for(int i = 1;i <= btot; i++) treecut[i] = 0;
        for(int i = 1;i <= btot+n; i++)  head[i] = -1;
        E = 0;
        for(int i = 1;i <= n; i++) if(iscut[i]) {
            sort(belo[i].begin(), belo[i].end());
            ditot++;
            treecut[ditot] = 1;
            newedge(belo[i][0], ditot);
            newedge(ditot, belo[i][0]);
            for(int j = 1;j < belo[i].size(); j++) if(belo[i][j] != belo[i][j-1]) {
                newedge(belo[i][j], ditot);
                newedge(ditot, belo[i][j]);
            }
        }
        solve(ditot);
    }
    return 0;
}

 

标签:Real,缩点,int,割点,++,edge,lca,roads,now
来源: https://www.cnblogs.com/Vocanda/p/12836835.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有