P1656 炸铁路
https://www.luogu.com.cn/problem/P1656
题意
- n个城市,m条铁路
- 只有一发炮弹,炸某一条路。让其不成互相连接
- 输出 必须按照 a 从小到大排序输出;如果a 相同,则根据 b从小到大排序。
1 2
5 6
想法
- 生成树+遍历
- 遍历每一条边,如果删除是否能够变为一个生成树
//
// Created by majoe on 2020/6/3.
//
#include <bits/stdc++.h>
using namespace std;
const int M = 5010,INF = 0x3f3f3f3f;
struct e{
int u,v;
}edges[M];
int n, m;
int p[160];
//大小拍好序,好输出
bool cmp(e e1, e e2){
if(e1.u == e2.u) return e1.v < e2.v;
else return e1.u < e2.u;
}
int find(int x){
if(x != p[x]) return p[x] = find(p[x]);
return p[x];
}
//判断是否能够生成生成树,如果可以,返回true
bool kruskal(int x){
for (int i = 1; i <= n; ++i) {
p[i] = i;
}
int cnt = 0;
//遍历所有除开 x 序号的边
for (int i = 0; i < m; ++i) {
if(i == x) continue;
auto t = edges[i];
t.u = find(t.u); t.v = find(t.v);
if(t.u != t.v){
p[t.u] = t.v;
cnt ++;
}
}
if (cnt >=n-1) return true;
else {
return false;
}
}
int main(){
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int a,b;
cin >> a >> b;
if(a > b) swap(a,b);
edges[i] = {a,b};//加入边
}
sort(edges,edges+m,cmp);
for (int i = 0; i < m; ++i) {
if(!kruskal(i)){
printf("%d %d\n",edges[i].u,edges[i].v);
}
}
return 0;
}