题目描述:
给定一个n个点m条边的无向图,求边双连通分量(e-dcc)数量。
输入:
第一行,n , m
接下来 m 行,每行两个整数 u , v,表示一条无向边 ( u , v )。
对于100%的数据,n,m <= 2 * 10 ^ 5。
输出:
共一行,输出值为边双连通分量数量。
样例输入:
6 7
1 2
2 3
3 1
3 4
4 5
5 6
4 6
样例输出:
2
提示:
无
题意解析:
题目让我们求边双连通分量的数量。
边双连通图是指,对一个无向图,任意两点之间都有两条路径相连通。
而边双连通分量即边双连通图的分支,子图。
具体实现:
我们可以先利用 Tarjan 算法,求出图的割边,然后将割边删除,那剩下的一个个独立的图便是边双连通分量,我们可以通过DFS对其进行染色,并最终求出其数量。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
vector<int> edge[N];
map<int, map<int, int> > mp;
int fa[N],dfn[N],low[N],ct;
int n,m;
void tarjan(int u)
{
ct++;
dfn[u]=ct;
low[u]=ct;
for (int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if (!dfn[v])
{
fa[v] = u;
tarjan(v);
low[u]=min(low[u],low[v]);
if (low[v]>low[u])
{
mp[u][v]=1;
mp[v][u]=1;
}
}
else if (v!=fa[u])
{
low[u]=min(low[u],dfn[v]);
}
}
}
int cnt;
int belong[N];
void dfs(int u)
{
belong[u]=cnt;
for (int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if (mp[u][v]) continue;
if (dfn[v])
{
dfn[v]=0;
dfs(v);
}
}
}
int main()
{
cin >> n >> m;
for (int i=1;i<=m;i++)
{
int u, v;
cin >> u >> v;
edge[u].push_back(v);
edge[v].push_back(u);
}
tarjan(1);//找割边
for (int i=1;i<=n;i++)
{
if (dfn[i])
{
++cnt;
dfn[i] = 0;
dfs(i);
}
}
int ans=0;//遍历计数
int check[N]={0};
for (int i =1;i<=n;i++)
{
if (!check[belong[i]])
{
ans++;
check[belong[i]]=1;
}
}
cout << ans << endl;
return 0;
}
总结:
Tarjan算法模板的应用