洛谷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\n",e[i].a,e[i].b); 44 } 45 return 0; 46 }
PS:~蒟蒻写博客不易,转载请注明出处,万分感谢!~