hdu2460 Network

来源:互联网 发布:九鼎下落知乎 编辑:程序博客网 时间:2024/06/05 07:59

思路:题目的意思是要求在原图中加边后桥的数量,首先我们可以通过Tarjan求边双连通分量,对于边(u,v),如果满足
low[v]>dfn[u],则为桥,这样我们就可以知道图中桥的数目了。对于每一次query,可以考虑dfs树,树边肯定是桥,然后连
上u,v这条边之后,就会形成一个环,这样环内的边就不是割边了,所以只要找到u,v的LCA,把这个路径上的桥标记为否就可以了。

const int maxn = 1e5 + 10;vector<vector<int> > G;int dfn[maxn], low[maxn], isbridge[maxn], mark[maxn], depth;int pre[maxn];int bridge_cnt;void dfs(int u, int fa) {    dfn[u] = low[u] = ++depth;    mark[u] = 1;    int first = 1;    int size = G[u].size();    for (int i = 0;i < size;++i) {        int v = G[u][i];        if (first && v == fa) {            first = 0;            continue;        }        if (dfn[v] == -1) {            pre[v] = u;            dfs(v, u);            low[u] = min(low[u], low[v]);            if (low[v] > dfn[u]) {//is bridge                isbridge[v] = 1;                bridge_cnt++;            }        }else if (mark[v]) low[u] = min(low[u], dfn[v]);    }}int calc(int u,int v) {    int ret = 0;    if (dfn[u] < dfn[v]) swap(u, v);    while(dfn[u] > dfn[v]) {        if (isbridge[u]) {            isbridge[u] = 0;            ret++;        }        u = pre[u];    }    while(dfn[v] > dfn[u]) {        if (isbridge[v]) {            isbridge[v] = 0;            ret++;        }        v = pre[v];    }    // while(u != v) {    //     if (isbridge[u]) {isbridge[u] = 0,ret++;}    //     if (isbridge[v]) {isbridge[v] = 0,ret++;}    //     u = pre[u];    //     v = pre[v];    // }    return ret;}/*int calc(int u,int v) {    int ret = 0;   // if (dfn[u] < dfn[v]) swap(u, v);    while(dfn[u] > dfn[v]) {        if (isbridge[u]) {            isbridge[u] = 0;            ret++;        }        u = pre[u];    }    while(dfn[v] > dfn[u]) {        if (isbridge[v]) {            isbridge[v] = 0;            ret++;        }        v = pre[v];    }    while(u != v) {        if (isbridge[u]) {isbridge[u] = 0,ret++;}        if (isbridge[v]) {isbridge[v] = 0,ret++;}        u = pre[u];        v = pre[v];    }    return ret;}*/int main(int argc, const char * argv[]){        // freopen("in.txt","r",stdin);    // freopen("out.txt","w",stdout);    // clock_t _ = clock();    int n, m;    while(scanf("%d%d", &n, &m) != EOF && n + m) {        G.clear();        G.resize(n + 2);        int u, v;        for (int i = 1;i <= m;++i) {            scanf("%d%d", &u, &v);            G[u].push_back(v);            G[v].push_back(u);        }        memset(dfn, -1,sizeof dfn);        memset(isbridge, 0, sizeof isbridge);        memset(mark, 0,sizeof mark);        depth = 0, bridge_cnt = 0;        dfs(1, -1);        scanf("%d", &m);        printf("Case %d:\n", ++nCase);        while(m--) {            scanf("%d%d", &u, &v);            int cnt = calc(u, v);            bridge_cnt -= cnt;            printf("%d\n", bridge_cnt);        }        printf("\n");    }    // printf("\nTime cost: %.2fs\n", 1.0 * (clock() - _) / CLOCKS_PER_SEC);    return 0;}
0 0
原创粉丝点击