题目大意:给出一张无向图(不一定联通,可能有重边),求出桥的数目,并按节点升序输出桥
题目思路:Tarjan求出桥,注意去掉重边
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<vector> #include<iostream> #include<algorithm> #define MAXSIZE 10005 #define LL long long using namespace std; vector<vector<int> >G; int vis[MAXSIZE],low[MAXSIZE],dfn[MAXSIZE],pre[MAXSIZE],Time,n,ans,son; struct node { int a,b; } point[MAXSIZE]; void Tarjan(int u,int fa) { pre[u]=fa; low[u]=dfn[u]=++Time; int len=G[u].size(),v,op=0; for(int i=0; i<len; i++) { v=G[u][i]; if(v==fa && !op)//若不存在重边那么执行这一步,low[u]将不被更新 { op=1; continue; } if(!dfn[v]) { Tarjan(v,u); low[u]=min(low[u],low[v]); } else//若存在重边执行这一步,low[u]将被更新,那么查找时便不满足dnf[pre[u]] < low[u],不计入桥 { low[u]=min(low[u],dfn[v]); } } } void Init() { memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis)); memset(pre,-1,sizeof(pre)); G.clear(); G.resize(n+1); Time=0; ans=0; son=0; } bool cmp(struct node A,struct node B) { if(A.a != B.a) return A.a > B.a?false:true; return A.b > B.b?false:true; } int main() { int a,b,m; while(scanf("%d",&n)!=EOF) { Init(); for(int i=0; i<n; i++) { scanf("%d",&a); getchar(); getchar(); scanf("%d",&m); getchar(); while(m--) { scanf("%d",&b); G[a].push_back(b); //G[b].push_back(a); } } for(int i=0; i<n; i++) { if(!dfn[i]) { Tarjan(i,-1); } } for(int i=0; i<n; i++) { int v=pre[i]; if(dfn[v]<low[i] && v!=-1) { point[ans].a=min(i,v); point[ans].b=max(i,v); ans++; } } printf("%d critical links ",ans); sort(point,point+ans,cmp); for(int i=0; i<ans; i++) { printf("%d - %d ",point[i].a,point[i].b); } printf(" "); } return 0; }