去重边:
对于无向图而言,网上主要两种写法,
第一种给每一条边的正反方向都分配一个相同但唯一的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 <iostream>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <algorithm>
#include <set>
#include <queue>
#include <string>
#include <map>
#include <stack>
#define MAXN 1004
#define MOD 1000000009
#define INF 0x7ffffff
#define lowbit(x) (x)&(-x)
using namespace std;
struct EDGE{
int next;
int to;
int w;
int id;
}edge[MAXN*MAXN];
int n,m;
int low[MAXN];
int dfn[MAXN];
int first[MAXN];
int cnt;
int total;
int ans;
void init(){
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(first,-1,sizeof(first));
cnt = total = 0;
ans = INF;
}
inline void add(int u,int v,int w,int id){
edge[total].to = v;
edge[total].w = w;
edge[total].next = first[u];
edge[total].id = id;
first[u] = total++;
}
void Tarjan1(int u,int 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){
continue;
}
if(!dfn[v]){
Tarjan1(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]);
}
}
}
void Tarjan2(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]){
Tarjan2(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]);
}
}
}
int main(){
while(cin >> n >> m && (n+m)){
init();
int u,v,w;
int id = 1;
while(m--){
cin >> u >> v >> w;
add(u,v,w,id);
add(v,u,w,id);
++id;
}
Tarjan1(1,-1);
// Tarjan2(1,1);
if(cnt != n) cout << 0 << endl;
else{
if(ans == INF){
cout << -1 << endl;
}
else cout << (ans == 0 ? 1 : ans) << endl;
}
}
return 0;
}