ContestHunter#24-C 逃不掉的路

Description:

求无向图的必经边

 思路:一眼题 将无向图缩成树,然后求两点树上距离

#include<iostream>
#include<vector> 
#include<cstring>
using namespace std;
const int N = 2e5 + 10;
 
int head[N], now = 1;
struct edges{
    int to, next;
}edge[N<<1];
void add(int u,int v){ edge[++now] = {v, head[u]}; head[u] = now;}
 
int n, m, dfn[N], low[N], cnt, tot, dict[N], Q, ans[N], dis[N], fa[N], vis[N];
bool bri[N<<1];
struct query{
    int to, id;
};
vector<query> q[N];
void q_add(int u, int v, int y){ q[u].push_back({v, y}); q[v].push_back({u, y}); }
void tarjan(int x, int in_edge){
    dfn[x] = low[x] = ++cnt;
    for(int i = head[x]; i; i = edge[i].next){
        int v = edge[i].to;
        if(!dfn[v]){
            tarjan(v, i);
            low[x] = min(low[x], low[v]);
            if(low[v] > dfn[x]) bri[i] = bri[i ^ 1] = 1;
        }
        else if(i != (in_edge ^ 1)) low[x] = min(low[x], dfn[v]);
    }
}
 
void dfs(int x){
    dict[x] = tot; vis[x] = 1;
    for(int i = head[x]; i; i = edge[i].next){
        int v = edge[i].to;
        if(vis[v] || bri[i]) continue;
        dfs(v);
    }
}
int get(int x){
    if(x != fa[x]) return fa[x] = get(fa[x]);
    return x;
}
void LCA(int x){
    vis[x] = 1;
    for(int i = head[x]; i; i = edge[i].next){
        int v = edge[i].to;
        if(vis[v]) continue;
        dis[v] = dis[x] + 1;
        LCA(v);
        fa[v] = x;
    }
    for(int i = 0; i < q[x].size(); i++){
        int v = q[x][i].to, id = q[x][i].id;
        if(vis[v] == 2){
            int lca = get(v); 
            ans[id] = min(ans[id], dis[x] + dis[v] - 2 * dis[lca]);
        }
    }
    vis[x] = 2;
}
struct input{
    int x, y;
}in[N];
int main(){
    scanf("%d%d", &n, &m);
    int x, y;
    for(int i = 1; i <= m; i++){
        scanf("%d%d", &x, &y);
        in[i] = {x, y};
        add(x, y); add(y, x);
    }
    for(int i = 1; i <= n; i++)
      if(!dfn[i]) tarjan(i, 0);
    for(int i = 1; i <= n; i++)
      if(!vis[i]) tot++, dfs(i);
    memset(head, 0, sizeof(head));
    memset(edge, 0, sizeof(edge)); now = 0;
    memset(vis, 0, sizeof(vis));
    for(int i = 1; i <= m; i++){
        x = dict[in[i].x], y = dict[in[i].y];
        if(x == y) continue;
        add(x, y), add(y, x);
    }
    scanf("%d", &Q);
    for(int i = 1; i <= Q; i++){
        scanf("%d%d", &x, &y);
        x = dict[x], y = dict[y];
        if(x == y) ans[i] = 0;
        else{
            q_add(x, y, i);
            ans[i] = 1e9;
        }
    }
    for(int i = 1; i <= n; i++) fa[i] = i;
    LCA(1);
    for(int i = 1; i <= Q; i++)
      printf("%d\n", ans[i]);
    return 0;
}
View Code

 

posted @ 2018-04-05 23:48  Ror_shach  阅读(452)  评论(0编辑  收藏  举报