zoj2588-tarjan求桥/割边

tarjan求桥,算法流程详见核心代码:

 1 void tarjan(int k){
 2     dfn[k]=low[k]=++cnt;
 3     //fa[k]=(edge){f,0,fid};
 4     for(int i=head[k];i;i=e[i].nxt){
 5         int v=e[i].to;
 6         if(!dfn[v]){
 7             fa[v]=e[i].id;//标记该边已走过,防止沿无向边返回 
 8             tarjan(v);
 9             low[k]=min(low[v],low[k]);
10         }else
11             if(fa[k]!=e[i].id)low[k]=min(low[k],dfn[v]);//在不走无向边的情况下更新low 
12     }
13     if(fa[k]&&low[k]==dfn[k])//若节点k的low=dfn则k在一个联通块中处于搜索树的顶部,那么节点k的父边一定为割边 
14         ans[++na]=fa[k]; 
15 }

模板题:zoj2588

题目大意:给出一个无向图,按顺序输出割边序号。

好久没用zoj,PE几次,若无割边要加个判断,以免多输出个0

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #define foru(i,x,y) for(int i=x;i<=y;i++)
 5 #define clr(x) memset(x,0,sizeof(x))
 6 using namespace std;
 7 const int N=10100;
 8 struct edge{int to,nxt,id;}e[210000];
 9 int head[N],dfn[N],low[N],ans[N],ne,na,cnt,n,m;
10 int fa[N];
11 void add(int a,int b,int c){
12     e[++ne]=(edge){b,head[a],c};head[a]=ne;
13 }
14 
15 void tarjan(int k){
16     dfn[k]=low[k]=++cnt;
17     //fa[k]=(edge){f,0,fid};
18     for(int i=head[k];i;i=e[i].nxt){
19         int v=e[i].to;
20         if(!dfn[v]){
21             fa[v]=e[i].id;//标记该边已走过,防止沿无向边返回 
22             tarjan(v);
23             low[k]=min(low[v],low[k]);
24         }else
25             if(fa[k]!=e[i].id)low[k]=min(low[k],dfn[v]);//在不走无向边的情况下更新low 
26     }
27     if(fa[k]&&low[k]==dfn[k])//若节点k的low=dfn则k在一个联通块中处于搜索树的顶部,那么节点k的父边一定为割边 
28         ans[++na]=fa[k]; 
29 }
30 
31 int main(){
32     int T,u,v;
33     scanf("%d",&T);
34     while(T--){
35         clr(e);clr(head);clr(dfn);clr(low);clr(fa);clr(ans);
36         ne=na=cnt=0;
37         scanf("%d%d",&n,&m);
38         foru(i,1,m){
39             scanf("%d%d",&u,&v);
40             add(u,v,i);add(v,u,i);
41         }
42         foru(i,1,n)
43             if(!dfn[i])tarjan(i);
44         sort(ans+1,ans+1+na);
45         printf("%d\n",na);
46         if(na){
47         foru(i,1,na-1)printf("%d ",ans[i]);printf("%d\n",ans[na]);}
48         if(T)printf("\n");
49     }
50     return 0;
51 }

 

转载于:https://www.cnblogs.com/y-m-y/p/6530206.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值