HDU 3686 Traffic Real Time Query System(點雙連通縮點 + LCA)

來源:互聯網
上載者:User

題意:

解題思路:

#include <stdio.h>#include <vector>#include <algorithm>using namespace std;#define pb push_backconst 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].pb(btot);                    belo[edge[now].to].pb(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];  // 縮點成樹後每個點是否為割點// RMQ 求lcavoid RMQ_init(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 LCAvoid 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);    }    RMQ_init(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;}


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.