危险道路(Tarjan+割边/桥)

时光总嘲笑我的痴心妄想 提交于 2019-11-28 19:04:57

题目描述

天凯是苏联的总书记。苏联有n个城市,某些城市之间修筑了公路。任意两个城市都可以通过公路直接或者间接到达。 天凯发现有些公路被毁坏之后会造成某两个城市之间无法互相通过公路到达。这样的公路就被称为dangerous pavement。 为了防止美帝国对dangerous pavement进行轰炸,造成某些城市的地面运输中断,天凯决定在所有的dangerous pavement驻扎重兵。可是到底哪些是dangerous pavement呢?你的任务就是找出所有这样的公路。

输入格式

第一行n,m(1<=n<=100000, 1<=m<=300000),分别表示有n个城市,总共m条公路。

以下m行每行两个整数a, b,表示城市a和城市b之间修筑了直接的公路。

输出格式

输出有若干行。每行包含两个数字a,b(a < b),表示 < a,b >是dangerous pavement。请注意:输出时,所有的数对< a,b>必须按照a从小到大排序输出;如果a相同,则根据b从小到大排序。

 

输入

6 6

1 2

2 3

2 4

3 5

4 5

5 6

 

输出

1 2

5 6

 

Tarjan算法割边的模板

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N=1e5+5;
 5 int n,m,dep;
 6 int dfn[N],low[N];
 7 vector<int> g[N];///邻接表存图
 8 vector<pair<int,int> > vec;///存割边
 9 pair<int,int> p;
10 
11 bool cmp(pair<int,int> x,pair<int,int> y){
12     return x.first==y.first?(x.second<y.second):(x.first<y.second);
13 }
14 
15 void tarjan(int u,int father){
16     dfn[u]=low[u]=++dep;
17     for(int i=0;i<g[u].size();i++){
18         int v=g[u][i];
19         if(v==father) continue;///无向图不能直接用父结点更新
20         if(!dfn[v]){
21             tarjan(v,u);
22             low[u]=min(low[u],low[v]);
23             if(low[v]>dfn[u]){///桥的判断方法
24                 p.first=min(u,v);
25                 p.second=max(u,v);
26                 vec.push_back(p);
27             }
28         }
29         else low[u]=min(low[u],dfn[v]);
30     }
31 }
32 
33 int main(){
34     scanf("%d%d",&n,&m);
35     while(m--){
36         int x,y;
37         scanf("%d%d",&x,&y);
38         g[x].push_back(y);///无向图,存双向边
39         g[y].push_back(x);
40     }
41     for(int i=1;i<=n;i++){
42         dep=0;///图未必连通,每次置为0
43         if(!dfn[i]){
44             tarjan(i,i);
45         }
46     }
47     sort(vec.begin(),vec.end(),cmp);
48     for(int i=0;i<vec.size();i++){
49         printf("%d %d\n",vec[i].first,vec[i].second);
50     }
51 }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!