无向图求桥 hdu4738 Caocao's Bridges

来源:互联网 发布:linux 安装hadoop 编辑:程序博客网 时间:2024/05/22 04:56

 

在边(u,v)中,若low[v]>dfn[u],则(u,v)为割边,但是实际处理时我们并不这样判断,因为有的图上可能有重边,这样不好处理。我们记录每条边的标号(一条无向边拆成的两条有向边标号相同),记录每个点的父亲到它的边的标号,如果边(u,v)是v的父亲边,就不能用dfn[u]更新low[v]。这样如果遍历完v的所有子节点后,发现dfn[u]<low[v],说明边(u,v)为割边。


代码:

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<queue>#include<vector>#include<stack>#include<string>#include<map>#include<cmath>#define clr(a,b) memset((a),b,sizeof((a)))#define PB(x) push_back(x)#define INF 0xfffffffusing namespace std;const int maxn=1010;const int maxm=maxn*maxn*2;int dfn[maxn],low[maxn],head[maxn];int num,tot;int ans;struct node{    int v,c,next,id;}e[maxm];int n,m;void tarjan(int u,int fa){    dfn[u]=low[u]=++num;    for(int i=head[u];~i;i=e[i].next){        int v=e[i].v;        int id=e[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,e[i].c);            }        }        else{            low[u]=min(low[u],dfn[v]);        }    }}void add(int u,int v,int c,int id){    e[tot].c=c;    e[tot].v=v;    e[tot].id=id;    e[tot].next=head[u];    head[u]=tot++;}int main(){    while(cin>>n>>m,n||m){        int u,v,c;        tot=0;        memset(head,-1,sizeof(head));        for(int i=1;i<=m;++i){            scanf("%d%d%d",&u,&v,&c);            add(u,v,c,i);            add(v,u,c,i);        }        memset(dfn,0,sizeof(dfn));        num=0;        int ok=0;        ans=INF;        for(int i=1;i<=n;++i)            if(!dfn[i]){                ok++;                tarjan(i,0);            }        if(ans==0) ans=1;        if(ans==INF) ans=-1;        if(ok>1) ans=0;        for(int i=1;i<=n;++i) cout<<dfn[i]<<"    "<<low[i]<<endl;        cout<<ans<<endl;    }    return 0;}


原创粉丝点击