去重边:
对于无向图而言,网上主要两种写法,
第一种给每一条边的正反方向都分配一个相同但唯一的id,那么在判断时如果两条边的id是一样的,就说明是一条边,这条边就不要走了。
在tarjan算法中,对于这种写法,传入参数就要有两个(出发点u,到达u的边的id)
void Tarjan(int u,int id){ //当前点u,来到u的边的id
low[u] = dfn[u] = ++cnt; //给定时间戳
for(int i=first[u];i!=-1;i=edge[i].next){
int v = edge[i].to;
if(id == edge[i].id){//id是相同,说明是同一条边,不要走
continue;
}
if(!dfn[v]){
Tarjan(v,edge[i].id);
low[u] = min(low[u],low[v]);
if(low[v] > dfn[u]){
if(edge[i].w < ans){
ans = edge[i].w;
}
}
}
else{
low[u] = min(low[u],dfn[v]);
}
}
}
第二种,如果有重边,对于两点而言,在邻接表中存储重边的先后顺序起码是一致的(即如果重边有两条,那么这两条边在两点的邻接表中存储顺序都是先一后二),所以说,利用这个特点和递归的性质,遇到的第一条边肯定是同一条边,不要走;如果再出现就说明有重边。
对于这种情况,Tarjan算法就要知道当前点和它的父亲节点才行,也就是传入参数改为当前点u和父节点f
void Tarjan(int u,int f){
low[u] = dfn[u] = ++cnt;
int flag = 0; //标记是否出现重边
for(int i=first[u];i!=-1;i=edge[i].next){
int v = edge[i].to;
if(v == f && !flag){ //同一条边,不要走
flag = 1;
continue;
}
if(!dfn[v]){
Tarjan(v,u);
low[u] = min(low[u],low[v]);
if(low[v] > dfn[u]){
if(edge[i].w < ans){
ans = edge[i].w;
}
}
}
else{
low[u] = min(low[u],dfn[v]);
}
}
}
这个题注意要注意重边。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include