hdu2460 poj3694 求桥 + 求lca

来源:互联网 发布:网络系统管理 编辑:程序博客网 时间:2024/04/30 19:25

http://poj.org/problem?id=3694
题意:
给定一个图,对这个图进行加边,求出每加一条边后,图中桥的个数。
思路:
首先肯定是要先求出原图中桥的个数,并且把桥标记起来。思考加一条边以后桥的数量会减少多少,联想到之前的那道题,就是加一条边,能够使桥的数量最少是多少。之前那个做法就是缩点后树的直径,这个就是可以减少的最多的桥的数量。因为如果这是一条链,将两个端点连起来,这上面的桥都消失了。。
所以按照这个思路,可以考虑,对于每个要加的边,求出他们的lca,在这个路径上如果碰到一个桥就减一。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <stack>#include <cmath>using namespace std;const int M_node = 100009;int low[M_node],dfn[M_node],father[M_node];bool isbridge[M_node]; //标记桥 树边<u,v> 是桥则 isbridge[v] = trueint dfs_clock,num_br;int n,m;vector<int> G[M_node];void init(){    for(int i = 0; i <= n;i++) G[i].clear();    memset(dfn,0,sizeof(dfn));    memset(isbridge,false,sizeof(isbridge));    num_br = dfs_clock = 0;}int dfs(int u,int fa){    father[u] = fa;    int lowu = dfn[u] = ++dfs_clock;    for(int i = 0;i < G[u].size();i++)    {        int v = G[u][i];        if(!dfn[v])        {            int lowv = dfs(v,u);            lowu = min(lowu,lowv);            if(lowv > dfn[u])            {                num_br++;                isbridge[v] = true;            }        }        else if(dfn[v] < dfn[u] && v != fa) lowu = min(lowu,dfn[v]);    }    low[u] = lowu;    return lowu;}void lca(int u,int v){    while(dfn[u] > dfn[v])    {        if(isbridge[u])        {            num_br--;            isbridge[u] = false;        }        u = father[u];    }    while(dfn[v] > dfn[u])    {        if(isbridge[v])        {            num_br--;            isbridge[v] = false;        }        v = father[v];    }    while(u != v)    {        if(isbridge[u])        {            num_br--;            isbridge[u] = false;        }        if(isbridge[v])        {            num_br--;            isbridge[v] = false;        }        u = father[u];        v = father[v];    }}int main(){    int k = 1;    //freopen("out.txt","w",stdout);    while(scanf("%d %d",&n,&m) == 2)    {        if(n == 0 || m == 0) break;        init();        for(int i = 0;i < m;i++)        {            int a,b;            scanf("%d %d",&a,&b);            G[a].push_back(b);            G[b].push_back(a);        }        dfs(1,-1);        int q;        scanf("%d",&q);        printf("Case %d:\n",k++);        while(q--)        {            int a,b;            scanf("%d %d",&a,&b);            lca(a,b);            printf("%d\n",num_br);        }        printf("\n");    }    return 0;}
0 0