ZOJ2588 Burning Bridges(割边模板)

题目要输出一个无向图的所有割边。用Tarjan算法:

一遍DFS,构造出一颗深度优先生成树,在原无向图中边分成了两种:树边(生成树上的边)和反祖边(非生成树上的边)。

顺便求出每个结点的DFS序dfn[u] 和 每个结点能沿着它和它的儿子的返祖边达到的结点最小的DFS序low[u]

一条边(u,v)是割边当且仅当——

  • low[v]>dfn[u]

注意具体实现时,无向图的边在邻接表中有正反两条边,那么如果一条边是树边了,另一条边不应该是反祖边,要忽略。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define MAXM 222222
 6 #define MAXN 11111
 7 struct Edge{
 8     int v,next;
 9     bool tag;
10 }edge[MAXM];
11 int NE,head[MAXN];
12 void addEdge(int u,int v){
13     edge[NE].v=v; edge[NE].next=head[u]; edge[NE].tag=0;
14     head[u]=NE++;
15 }
16 int dn,dfn[MAXN],low[MAXN],res[MAXM],resn;
17 void dfs(int u){ 
18     dfn[u]=low[u]=++dn;
19     for(int i=head[u]; i!=-1; i=edge[i].next){
20         if(edge[i].tag) continue;
21         int v=edge[i].v;
22         if(dfn[v]){
23             low[u]=min(low[u],dfn[v]);
24             continue;
25         }
26         edge[i].tag=edge[i^1].tag=1;
27         dfs(v);
28         low[u]=min(low[u],low[v]);
29         if(low[v]>dfn[u]) res[resn++]=(i>>1)+1;
30     }
31 }
32 int main(){
33     int t,n,m,a,b;
34     scanf("%d",&t);
35     while(t--){
36         scanf("%d%d",&n,&m);
37         NE=0;
38         memset(head,-1,sizeof(head));
39         while(m--){
40             scanf("%d%d",&a,&b);
41             addEdge(a,b); addEdge(b,a);
42         }
43         resn=dn=0;
44         memset(dfn,0,sizeof(dfn));
45         dfs(1);
46         printf("%d\n",resn);
47         sort(res,res+resn);
48         for(int i=0; i<resn; ++i){
49             if(i) putchar(' ');
50             printf("%d",res[i]);
51         }
52         if(resn) putchar('\n');
53         if(t) putchar('\n');
54     }
55     return 0;
56 }

 

posted @ 2016-01-23 20:26  WABoss  阅读(257)  评论(0编辑  收藏  举报