题目大意:
给一个连通图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]