您的位置:首页 > 其它

hdu 4738

2015-08-14 01:13 344 查看
tarjan算法;

无向联通图求割边,这道题需要处理的是重边问题,将无向图化为有向图可以解决重边问题;

至于为什么,可以画一个简单的重边无向图模拟这个算法,加深理解。(主要是我担心自己的理解未必正确,而且模拟起来不难)

//hdu 4738   tarjan模板;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
#define maxn 0x3f3f3f3f

struct Edge{
int to, next, w, id;
}edge[1005*1005*2];
int n, m, cnt, ans, dfnClock;
int dfn[1005], low[1005], head[1005];

void addEdge(int u, int v, int w, int id){   //链式前向星:
edge[cnt].w = w;
edge[cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].id = id;
head[u] = cnt++;
}

void tarjan(int u, int fa){
dfn[u] = low[u] = ++dfnClock;
for(int i = head[u]; ~i; i = edge[i].next){   //枚举和u,联通的边;
int v = edge[i].to;
int id = edge[i].id;
if(fa == id) continue;  // 之前已经访问过这条边(方向变换)
if(!dfn[v]){
tarjan(v, id);
low[u] = min(low[u], low[v]);
if(dfn[u] < low[v])
ans = min(ans, edge[i].w);
}
else
low[u] = min(low[u], dfn[v]);
}
return ;
}

int main()
{
while(scanf("%d%d", &n, &m) != EOF && (n||m)){
cnt = 0;
int u, v, w;
memset(head, -1, sizeof(head));
for(int i = 1; i <= m; ++i){
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w, i);   //将一条无向边转变为两条有向边;
addEdge(v, u, w, i);
}
ans = maxn;
dfnClock = 0;
int tot = 0;     //判断无向图是否联通;
memset(dfn, 0, sizeof(dfn));
for(int i = 1; i <= n; ++i){
if(!dfn[i]){
++tot;
tarjan(i, 0);
}
}
if(ans == maxn) ans = -1;
if(ans == 0) ans = 1;
if(tot > 1) ans = 0;
printf("%d\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: