洛谷P1656 炸铁路

题目

题目描述

因为某国被某红色政权残酷的高压暴力统治。美国派出将军uim,对该国进行战略性措施,以解救涂炭的生灵。

该国有n个城市,这些城市以铁路相连。任意两个城市都可以通过铁路直接或者间接到达。

uim发现有些铁路被毁坏之后,某两个城市无法互相通过铁路到达。这样的铁路就被称为key road。

uim为了尽快使该国的物流系统瘫痪,希望炸毁铁路,以达到存在某两个城市无法互相通过铁路到达的效果。

然而,只有一发炮弹(美国国会不给钱了)。所以,他能轰炸哪一条铁路呢?

输入输出格式

输入格式:

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

以下m行,每行两个整数a, b,表示城市a和城市b之间有铁路直接连接。

输出格式:

输出有若干行。

每行包含两个数字a,b(a<b),表示<a,b>是key road。

请注意:输出时,所有的数对<a,b>必须按照a从小到大排序输出;如果a相同,则根据b从小到大排序。

输入输出样例

输入样例#1:
6 6
1 2
2 3
2 4
3 5
4 5
5 6
输出样例#1:
1 2
5 6

Solution:

开始以为这是道sb题木,直接统计入度为0的不就好了吗?结果撸好代码一交只对了1个点,再仔细看题,发现不能这样做。题目要求的其实是有向图中的割边,正解应该是Tarjan,但是这道题数据如此之小,直接暴力搜索或者各种奇技淫巧来做。我这里用的是类似于Kruskal的算法来做的,实际上就是对边双关键字排序(因为输出要求),然后枚举删除的一条边,按照Kruskal的方法去做看是否能生成生成树,若不能则输出一个答案(调试并查集调了我好久,太菜了~~)。时间复杂度O(m2),完全能过。

代码:

 1 #include<bits/stdc++.h>
 2 #pragma GCC optimize(2)
 3 using namespace std;
 4 #define ll long long
 5 #define il inline
 6 #define inf 233333333
 7 int n,m,fla,fa[250],tot;
 8 struct edge{
 9 int a,b;
10 }e[5200];
11 il bool cmp(edge a,edge b)
12 {
13     if(a.a<b.a)return 1;
14     if(a.a==b.a&&a.b<b.b)return 1;
15     return 0;
16 }
17 il int find(int x)
18 {
19     if(fa[x]!=x)fa[x]=find(fa[x]);
20     return fa[x];
21 }
22 il void unionn(int x,int y)
23 {
24     int a=find(x),b=find(y);
25     if(a!=b)fa[a]=b,tot++;
26 }
27 int main()
28 {
29     scanf("%d%d",&n,&m);
30     for(int i=1;i<=m;i++){
31     scanf("%d%d",&e[i].a,&e[i].b);
32     if(e[i].a>e[i].b)swap(e[i].a,e[i].b);
33     }
34     sort(e+1,e+m+1,cmp);
35     for(int i=1;i<=m;i++)
36     {
37         tot=0;
38         for(int j=1;j<=n;j++)fa[j]=j;
39         for(int j=1;j<=m;j++){
40         if(i!=j)unionn(e[j].a,e[j].b);
41         if(tot==n-1)break;
42         }
43         if(tot!=n-1)printf("%d %d
",e[i].a,e[i].b);
44     }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/five20/p/7793764.html