判断无向图的割点和桥的模板题,但是这个题要求按照输入的顺序输出边,因此需要把边保存以下,挺麻烦的其实,= =。
#include <map>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX = 10010;
typedef pair <int, int> Pii;
vector <int> vt[MAX];
vector <Pii> ans;
map <string, int> mp;
map <Pii, int> order;
string a, b, name[MAX];
int n, m;
bool vis[MAX];
int cnt_n, cnt_e,dfs_clock;
int pre[MAX];
void init(){
for(int i=1; i<=n; i++){
vt[i].clear();
pre[i] = 0;
vis[i] = false;
}
mp.clear();
ans.clear();
order.clear();
cnt_e = cnt_n = dfs_clock = 0;
}
void is_connected(int u){//判断是否连通
vis[u] = true;
for(int i=0; i<vt[u].size(); i++){
int v = vt[u][i];
if(!vis[v]) is_connected(v);
}
}
bool presolve(){
for(int i=1; i<=n; i++)
if(!vis[i]) return false;
return true;
}
int dfs(int u, int fa){//tarjan算法求桥
int lowu = pre[u] = ++dfs_clock;
for(int i=0; i<vt[u].size(); i++){
int v = vt[u][i];
if(!pre[v]){
int lowv = dfs(v, u);
lowu = min(lowu, lowv);
if(lowv > pre[u]){
Pii tmp;
tmp.first = u, tmp.second = v;
if(order[tmp] == false)
tmp.first = v, tmp.second = u;
ans.push_back(tmp);
}
}
else if(pre[v] < pre[u] && v != fa)
lowu = min(lowu, pre[v]);
}
return lowu;
}
bool cmp(Pii A, Pii B){
return order[A] < order[B];
}
int main(){
int cas;
scanf("%d",&cas);
while(cas--){
scanf("%d%d",&n,&m);
init();
for(int i=0; i<m; i++){
cin >> a >> b;
if(mp[a] == false){
mp[a] = ++cnt_n;
name[cnt_n] = a;
}
if(mp[b] == false){
mp[b] = ++cnt_n;
name[cnt_n] = b;
}
int u = mp[a], v = mp[b];
vt[u].push_back(v);
vt[v].push_back(u);
Pii tmp;
tmp.first = u, tmp.second = v;
order[tmp] = ++cnt_e;
}
is_connected(1);
if(!presolve()){
puts("0");
continue;
}
dfs(1, -1);
int l = ans.size();
printf("%d\n",l);
sort(ans.begin(), ans.end(), cmp);
for(int i=0; i<l; i++){
cout << name[ans[i].first] << " " << name[ans[i].second] << endl;
}
}
return 0;
}