题意 : N个点M条边,允许有重边,让你求出割边的数目以及每条割边的编号(编号是输入顺序从1到M)。
思路 :tarjan求割边,对于除重边以为中生成树的边(u,v),若满足dfn[u] < low[v],则边(u,v)是割边。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 struct node 9 { 10 int u ; 11 int v; 12 int next ; 13 int num ; 14 }p[200100]; 15 int dfn[200100],low[200100] ;//dfn深度优先遍历生成树的顺序,low表示该节点能够到达的祖先的最小编号 16 int bridge[200100] ,nbrid,vis[200010];//桥的编号,割边的条数,vis表示该点是否访问过 17 int cnt,head[200100],tot ; 18 19 void Init() 20 { 21 cnt = nbrid = tot= 0 ; 22 memset(head,-1,sizeof(head)) ; 23 memset(vis,0,sizeof(vis)) ; 24 } 25 void addedge(int u,int v,int id) 26 { 27 //p[cnt].u = u ; 28 p[cnt].v = v ; 29 p[cnt].num = id ; 30 p[cnt].next = head[u] ; 31 head[u] = cnt ++ ; 32 //p[cnt].u = v ; 33 p[cnt].v = u ; 34 p[cnt].num = id ; 35 p[cnt].next = head[v] ; 36 head[v] = cnt ++ ; 37 } 38 39 void DFS(int u,int fu) 40 { 41 dfn[u] = low[u] = tot++ ; 42 vis[u] = 1 ; 43 for(int i = head[u] ; i != -1 ; i = p[i].next) 44 { 45 int v = p[i].v; 46 if(p[i].num != fu && vis[v] ) 47 { 48 low[u] = min(low[u],dfn[v]) ; 49 } 50 else if( !vis[v] ) 51 { 52 DFS(v,p[i].num) ; 53 low[u] = min(low[u],low[v]) ; 54 if(low[v] > dfn[u]) 55 { 56 bridge[++nbrid] = p[i].num; 57 } 58 } 59 } 60 } 61 int main() 62 { 63 int T ,N,M,u,v; 64 scanf("%d",&T) ; 65 while(T--) 66 { 67 Init() ; 68 scanf("%d %d",&N,&M) ; 69 for(int i = 1 ; i <= M ; i++) 70 { 71 scanf("%d %d",&u,&v) ; 72 addedge(u,v,i) ; 73 } 74 DFS(1,-1) ; 75 sort(bridge+1,bridge+1+nbrid) ; 76 printf("%d\n",nbrid) ; 77 for(int i = 1 ; i <= nbrid ; i++) 78 { 79 if(i != nbrid) 80 printf("%d ",bridge[i]) ; 81 else printf("%d\n",bridge[i]) ; 82 } 83 if(T)puts("") ; 84 } 85 return 0; 86 }