危险的桥

【题目描述】

有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;
}
posted @ 2016-10-27 20:10  前前前世。  阅读(226)  评论(0编辑  收藏  举报