POJ 3694 Network

题目大意:

给一个连通图G,问加入某一条边后图中还有多少割边。


解题思路:

1、用Tarjan算法求出所有的割边和每一个点的父节点,并记录。记录每一个节点的父节点可以形成一棵深搜树。

2、通过求LCA(最近公共祖先)的过程中对于深搜树的处理,记录经过的割边的数量并减去。


注意事项:

1、因为数据比较大,所以每加一次边用Tarjan求一次割边数量是不现实的,并且是不符合题意的。因为某两个点之间原来有一条边,现在再加一条。这样的情况他俩之间就没有割边了。

2、当DFN[U]

3、求LCA是没有模板的,但是有一点必须要办的是就要生成一棵树。这样才能求LCA。


下面是代码:

#include 
#include 
const int MAXN=100005;
struct node
{
    int to,next;
} edge[MAXN*4];
int head[MAXN],dfn[MAXN],low[MAXN],pre[MAXN],vis[MAXN],n,m,time,cnt,cut;
bool bi[MAXN];
void init()
{
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    for(int i=0; i<=n; pre[i]=i,i++);
    memset(bi,0,sizeof(bi));
    cnt=0;
    cut=0;
    time=1;
}
int min(int a,int b)
{
    if(a>b)a=b;
    return a;
}
void addedge(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt;
    cnt++;
}
void dfs(int u,int fa)
{
    dfn[u]=time;
    low[u]=time;
    time++;
    vis[u]=1;
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].to;
        if(!vis[v])
        {
            dfs(v,u);
            pre[v]=u;   //记录父节点
            low[u]=min(low[u],low[v]);
            if(low[v] > dfn[u])   //如果子节点的low值大于父节点的时间戳这就是桥
            {
                cut++;
                bi[v] = true;
            }
        }
        else if(vis[v] == 1 && v != fa)
        {
            low[u]=min(low[u],dfn[v]);
        }
    }
    vis[u]=2;
}
int judge(int u,int v)
{
    int cnt1=0;
    while(dfn[u]>dfn[v])
    {
        if(bi[u])
        {
            cnt1++;
            bi[u]=false;
        }
        u=pre[u];
    }
    while(dfn[u]


转载于:https://www.cnblogs.com/lin375691011/p/3996697.html

你可能感兴趣的:(POJ 3694 Network)