题意:
n个点的无向图,求桥边个数,求属于多个环的边的个数。
BCC裸题?
跑一次tarjan都可以求出来啦。
#include <cstdio>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn = 10005, maxm = 100005;
int n, m, head[maxn], cnt, low[maxn], dfn[maxn], ans1, ans2, clo;
bool inbcc[maxn];
struct _edge {
int v, next;
} g[maxm << 1];
stack<int> sta;
vector<int> bcc;
inline int iread() {
int f = 1, x = 0; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
return f * x;
}
inline void add(int u, int v) {
g[cnt] = (_edge) {v, head[u]};
head[u] = cnt++;
}
inline void update() {
for(int i = 1; i <= n; i++) inbcc[i] = 0;
for(int i = 0; i < bcc.size(); i++) inbcc[bcc[i]] = 1;
int tot = 0;
for(int j = 0; j < bcc.size(); j++) for(int i = head[bcc[j]]; ~i; i = g[i].next) if(inbcc[g[i].v])
tot++;
tot >>= 1;
if(tot > bcc.size()) ans2 += tot;
}
void tarjan(int x, int f) {
low[x] = dfn[x] = ++clo;
sta.push(x);
for(int i = head[x]; ~i; i = g[i].next) {
int v = g[i].v;
if(v == f) continue;
if(!dfn[v]) {
tarjan(v, x);
low[x] = min(low[x], low[v]);
if(low[v] > dfn[x]) ans1++;
if(low[v] >= dfn[x]) {
bcc.clear();
while(1) {
int u = sta.top(); sta.pop();
bcc.push_back(u);
if(u == v) break;
}
bcc.push_back(x);
update();
}
}
else
low[x] = min(low[x], dfn[v]);
}
}
int main() {
while(1) {
n = iread(); m = iread();
if(n == 0 && m == 0) break;
for(int i = 1; i <= n; i++) low[i] = dfn[i] = 0, head[i] = -1; cnt = 0;
while(m--) {
int u = iread(), v = iread();
u++; v++;
add(u, v); add(v, u);
}
ans1 = ans2 = clo = 0;
for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i, 0);
printf("%d %d\n", ans1, ans2);
}
return 0;
}