加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

POJ PKU 3694 割边 lca

(2010-09-28 21:31:38)
标签:

poj

pku

3694

割边

lca

it

分类: 图论

题目描述:给你一个无向连通图,然后陆续加一些边。

每加一条边,让你输出当前图的割边有多少条。

解题报告:

开始时先统计所有割边的个数(tarjan),然后每加一条边,只会减少割边的个数。

随机取一个根,建立dfs树,确定每一个点的father。

这样,每当连接点a和点b这条边,会就形成一个环,这个环内的边都不是割边。

所以只要找到a,b的lca,把这个路径上的桥标记掉就好了。

代码如下:

#include<iostream>

#include<vector>

using namespace std;

#define N 100001

vector<int> v[N];

int n, m, q, a, b, dfn[N], low[N], num, index, fa[N], level[N];

bool isbridge[N];

void tarjan(int id, int from, int deep)

{

    fa[id] = from, low[id] = dfn[id] = ++index;

    level[id] = deep;

    bool flag = false;

    for(int i = 0; i < v[id].size(); i++)

        if (v[id][i] == from && !flag) flag = true;

        else

        {

            if (!dfn[v[id][i]])

            {

                tarjan(v[id][i], id, deep + 1);

                low[id] = min(low[id], low[v[id][i]]);

                if (low[v[id][i]] > dfn[id])

                {

                    isbridge[v[id][i]] = 1;

                    num++;

                }

            }

            else low[id] = min(low[id], dfn[v[id][i]]);

        }

}

void lca(int u, int v)

{

    if (level[u] < level[v]) swap(u, v);

    while(level[u] > level[v])

    {

        if (isbridge[u])

        {

            num--;

            isbridge[u] = 0;

        }

        u = fa[u];

    }

    while(v != u)

    {

        if (isbridge[u])

            num--, isbridge[u] = 0;

        if (isbridge[v])

            num--, isbridge[v] = 0;

        u = fa[u], v = fa[v];

    }

}

int main()

{

    int ca = 1;

    while(scanf("%d%d", &n, &m) && (n || m))

    {

        for(int i = 1; i <= n; i++) v[i].clear();

        while(m-- && scanf("%d%d", &a, &b))

            v[a].push_back(b), v[b].push_back(a);

        index = 0, num = 0;

        memset(isbridge, 0, sizeof(bool) * (n + 1));

        memset(dfn, 0, sizeof(int) * (n + 1));

        tarjan(1, -1, 0);

        scanf("%d", &q);

        printf("Case %d:\n", ca++);

        while(q-- && scanf("%d%d", &a, &b))

            lca(a, b), printf("%d\n", num);

        putchar('\n');

    }

    return 0;

}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有