hdu2460 poj3694 求桥 + 求lca

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] = true
int 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;
}
时间: 2024-08-01 18:16:03

hdu2460 poj3694 求桥 + 求lca的相关文章

POJ 3694——Network——————【连通图,LCA求桥】

Network Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 3694 Description A network administrator manages a large network. The network consists of N computers and M links between pairs of compute

hdu2460&amp;&amp;poj3694 缩点+lca变形

http://acm.hdu.edu.cn/showproblem.php?pid=2460 http://poj.org/problem?id=3694 Problem Description A network administrator manages a large network. The network consists of N computers and M links between pairs of computers. Any pair of computers are c

tarjan算法求桥双连通分量 POJ 3177 Redundant Paths

POJ 3177 Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12598   Accepted: 5330 Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the re

HDU 4738 无向图求桥

使用tarjan算法求桥,模板题,但是... 1.有重边 2.不一定连通 3.没有人守桥至少要派一个人去 http://acm.hdu.edu.cn/showproblem.php?pid=4738 这种题挺好的,可以锻炼人的耐性和心理承受能力... #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <vector> us

HDU 4738 Caocao&#39;s Bridges tarjan求桥

Caocao's Bridges Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Chan

UVA 796 - Critical Links【求桥】

link:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=737 题意: 求桥的数目及边,要求输出边的点的次序由小到大 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include

Tarjan求桥和割点

//Tarjan 求桥和割点 Tarjan(u,fa) { DFN[u]=LoW[u]=++time; Cu=grey; for each e=(u,v) { Tarjan(v,u); if(Cv=white) { low[u]=min(low[u],low[v]); }else { low[u]=min(low[u],DFN[v]); } } }

tarjan求桥、割顶

若low[v]>dfn[u],则(u,v)为割边.但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理.我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父亲到它的边的标号,如果边(u,v)是v的父亲边,就不能用dfn[u]更新low[v].这样如果遍历完v的所有子节点后,发现low[v]=dfn[v],说明u的父亲边(u,v)为割边. void tarjan(int x) { vis[x]=1; dfn[x]=low[x]=++num; for(int i

hdoj 4738 Caocao&#39;s Bridges【双连通分量求桥】

Caocao's Bridges Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3000    Accepted Submission(s): 953 Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. Bu