危险的桥
【题目描述】
有n(n <= 200)座城市,某些城市之间修筑了公路,任意两座城市都能够通过公路直接或间接相连。
现询问有哪些公路被破坏后,将会使某两座城市无法连接。
【输入描述】
第一行输入两个正整数n、m(m <= 500),表示城市数目和道路数目;
接下来m行,每行输入两个数A、B,表示A、B两座城市之间存在道路。
【输出描述】
输出若干行,每行包含两个整数,分别表示合法公路相连的两座城市A、B(A < B),按字典序排列。
【样例输入】
6 6
1 2
2 3
2 4
3 5
4 5
5 6
【样例输出】
1 2
5 6
源代码: #include<cstdio> #include<algorithm> using namespace std; struct Node { int To,From,Next; }Edge[1001],Ans[501]; int m,n,Sum(0),Num(0),Number(0),i[201],j[201],Head[201]; bool Bridge[1001]; bool Rule(Node t1,Node t2) { return t1.From!=t2.From?t1.From<t2.From:t1.To<t2.To; } void Add(int t1,int t2) //边表。 { Edge[++Sum].To=t2; Edge[Sum].From=t1; Edge[Sum].Next=Head[t1]; Head[t1]=Sum; } void Tarjan(int t,int Father) //Tarjan求桥割类。 { i[t]=j[t]=++Num; for (int a=Head[t];a;a=Edge[a].Next) { int T=Edge[a].To; if (!j[T]) { Tarjan(T,t); i[t]=min(i[t],i[T]); if (i[T]>j[t]) //翻不到上头又是直连边,为桥。 Bridge[a]=true; } else if (T!=Father) i[t]=min(i[t],j[T]); } } int main() //裸Tarjan求桥。 { scanf("%d%d",&n,&m); for (int a=1;a<=m;a++) { int t1,t2; scanf("%d%d",&t1,&t2); Add(t1,t2); Add(t2,t1); } for (int a=1;a<=n;a++) if (!j[a]) Tarjan(a,0); for (int a=1;a<=Sum;a++) if (Bridge[a]) { if (Edge[a].From>Edge[a].To) //字典序排列。 swap(Edge[a].From,Edge[a].To); Ans[++Number]=Edge[a]; } sort(Ans+1,Ans+Number+1,Rule); //字典序排列。 for (int a=1;a<=Number;a++) printf("%d %d\n",Ans[a].From,Ans[a].To); return 0; }