题目链接:https://ac.nowcoder.com/acm/contest/392/I
题意:给你一个连通的无向图,问图的隔边有多少条
输入:N,M分别是点数和边数
之后M行每行两个正整数u,v表示无向边
强连通分量:如果一个有向图任意两点都是互相可达的,这个图就是强连通分量
不过我们这个题是无向图,所以要改一点
这个博客讲的还蛮好的:https://blog.csdn.net/mengxiang000000/article/details/51672725
不过他说的有一点有问题,如果在遍历一个点的边时,边已经被访问过了,那作比较的就不是两个点的low值了,而是自己的low值和下一个点的dfn值
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf=1<<30; const int maxn=1e5+7; const double pi=acos(-1); const int mod=1000000007; int n,m,cnt,ans,dfn[maxn],low[maxn]; vector<int> v[maxn]; inline void read(int &x){ char ch=x=0; while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) x=x*10+ch-‘0‘,ch=getchar(); } void Tarjan(int now,int fa){ dfn[now]=low[now]=++cnt; for(int i=0;i<v[now].size();i++){ if(!dfn[v[now][i]]){//如果这个点还没有被走过,就走这个点,如果走过dfn肯定被定义过,直接用dfn判断,省一个vis数组 Tarjan(v[now][i],now);//对这个点再用Tarjan算法,并记得把父亲给传过去 low[now]=min(low[now],low[v[now][i]]);//等走完之后再来更新本节点的low值,没走过就是两个low比 if(low[v[now][i]]>dfn[now]) ans++;//回溯之后如果now和其子节点在同一个强连通分量里,子节点的low值应该更新为 //now的dfn值(因为是从now节点更新的,一个强连通分量里仅有一个特殊的点,就是起始点,其他店的low值都会更新为 //它的,所以若不同则说明不再一个强连通分量里 ) } else if(v[now][i]!=fa) low[now]=min(low[now],dfn[v[now][i]]); //如果已经走过且不是父亲的话(因为是无向边所以还要标记父亲),那就更新节点的low值吧 } } int main(){ scanf("%d%d",&n,&m); int x,y; int t=m; while(t--){ scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } Tarjan(1,0);//因为题目说过保证联通,所以不需要再用for循环 //cout<<ans<<" "<<m<<endl; cout<<m-ans<<endl; return 0; }
牛客小白月赛12 I 华华和月月逛公园 Tarjan算法求隔边
原文:https://www.cnblogs.com/qingjiuling/p/10554812.html