第一个答案是统计图中桥的个数

如果一个点-双连通分量中边的个数大于点的个数那么这个块中所有的边都是冲突的,累加到第二个答案中去。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
#define MP make_pair
#define Ft first
#define Sd second
using namespace std; typedef pair<int, int> PII; const int maxn = + ; int n, m; vector<int> G[maxn]; vector<PII> bcc[maxn];
stack<PII> S;
int pre[maxn], low[maxn], dfs_clock, bcc_cnt; int ans1, ans2; void dfs(int u, int fa)
{
low[u] = pre[u] = ++dfs_clock;
for(int i = ; i < G[u].size(); i++)
{
int v = G[u][i];
if(!pre[v])
{
S.push(MP(u, v));
dfs(v, u);
low[u] = min(low[u], low[v]); if(low[v] >= pre[u])
{
bcc_cnt++;
bcc[bcc_cnt].clear();
for(;;)
{
PII x = S.top(); S.pop();
bcc[bcc_cnt].push_back(x);
if(x.Ft == u && x.Sd == v) break;
}
if(low[v] > pre[u]) ans1++; //bridge
}
}
else if(v != fa && pre[v] < pre[u])
{
S.push(MP(u, v));
low[u] = min(low[u], pre[v]);
}
}
} void find_bcc()
{
memset(pre, , sizeof(pre));
dfs_clock = bcc_cnt = ;
for(int i = ; i < n; i++) if(!pre[i]) dfs(i, -);
} bool vis[maxn]; int main()
{
while(scanf("%d%d", &n, &m) == && n)
{
for(int i = ; i < n; i++) G[i].clear();
while(m--)
{
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
} ans1 = ans2 = ;
find_bcc(); for(int i = ; i <= bcc_cnt; i++)
{
memset(vis, false, sizeof(vis));
int vertex = , sz = bcc[i].size();
for(int j = ; j < sz; j++)
{
PII x = bcc[i][j];
if(!vis[x.Ft]) { vis[x.Ft] = true; vertex++; }
if(!vis[x.Sd]) { vis[x.Sd] = true; vertex++; }
}
if(sz > vertex) ans2 += sz;
} printf("%d %d\n", ans1, ans2);
} return ;
}

代码君

05-02 19:13