题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588
题意:Ferry王国有n个岛,m座桥,每个岛都可以互达,现在要烧毁一些桥使得,但烧毁后每个岛仍可以互达,问哪些桥肯定不会被烧毁。
分析:给定一个无向连通图,要求图中的割边。注意,图中可能有重边,只要顶点u和v之间有重边,则这些重边任何一条都不可能是割边。这题的输出比较坑,pe了好多次。。。
AC代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=10000+5; 6 const int M=100000+5; 7 struct EDGE{ 8 int v,id,next; 9 }edge[M*2]; 10 int first[N],low[N],dfn[N],bri[M]; 11 int g,cnt,top,ans; 12 int min(int a,int b) 13 { 14 return a<b?a:b; 15 } 16 void AddEdge(int u,int v,int id) 17 { 18 edge[g].v=v; 19 edge[g].id=id; 20 edge[g].next=first[u]; 21 first[u]=g++; 22 } 23 void Tarjan(int u,int fa) 24 { 25 int i,v; 26 low[u]=dfn[u]=++cnt; 27 for(i=first[u];i!=-1;i=edge[i].next) 28 { 29 v=edge[i].v; 30 if(i==(fa^1)) 31 continue; 32 if(!dfn[v]) 33 { 34 Tarjan(v,i); 35 low[u]=min(low[u],low[v]); 36 if(low[v]>dfn[u]) 37 { 38 bri[top++]=edge[i].id; 39 ans++; 40 } 41 } 42 else 43 low[u]=min(low[u],dfn[v]); 44 } 45 } 46 int main() 47 { 48 int t,n,m,i,u,v; 49 scanf("%d",&t); 50 while(t--) 51 { 52 g=cnt=top=ans=0; 53 memset(first,-1,sizeof(first)); 54 memset(low,0,sizeof(low)); 55 memset(dfn,0,sizeof(dfn)); 56 memset(bri,M,sizeof(bri)); 57 scanf("%d%d",&n,&m); 58 for(i=1;i<=m;i++) 59 { 60 scanf("%d%d",&u,&v); 61 AddEdge(u,v,i); 62 AddEdge(v,u,i); 63 } 64 for(i=1;i<=n;i++) 65 if(!dfn[i]) 66 Tarjan(i,-1); 67 sort(bri,bri+top); 68 printf("%d\n",ans); 69 for(i=0;i<top;i++) 70 { 71 printf("%d",bri[i]); 72 if(i!=top-1) 73 printf(" "); 74 } 75 if(top) 76 printf("\n"); 77 if(t) 78 printf("\n"); 79 } 80 return 0; 81 }