【题目描述】
某岛屿上有N个旅游景点,任意两个旅游景点之间能够连通,但道路部门正在对某条道路进行施工,禁止游客通行,为了使所有旅游景点依然能够正常开放,道路部门决定搭建一些临时桥梁,使得无论哪条道路正在进行施工,游客都能够到达所有的旅游景点。
现询问至少搭建多少条临时桥梁,在施工期间,游客也能够到达所有的旅游景点。
【输入描述】
第一行输入两个整数N、M(N、M <= 1000),表示景点数目以及道路数目;
接下来M行,每行输入两个整数A、B,表示景点A、B之间存在一条直连道路。
【输出描述】
输出一个数,表示答案。
【输入样例】
样例1:
10 12
1 2
1 3
1 4
2 5
2 6
5 6
3 7
3 8
7 8
4 9
4 10
9 10
样例2:
3 3
1 2
2 3
1 3
【输出样例】
样例1:
2
样例2:
0
源代码: #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; vector <int> List[1001]; int n,m,Num(0),Ans(0),i[1001],j[1001],Vis[1001],Sum[1001]; void DFS(int t,int Father) //稍加修改的Tarjan。 { Vis[t]=1; j[t]=i[t]=++Num; for (int a=0;a<List[t].size();a++) { int T=List[t][a]; if (Vis[T]==1&&T!=Father) //防重复,其实想一想,朴素Tarjan的Instack()其实也如此。 i[t]=min(i[t],j[T]); if (!Vis[T]) { DFS(T,t); i[t]=min(i[t],i[T]); } } Vis[t]=2; //其实加不加都无所谓,Vis[0]、Vis[1]、Vis[2]分别表示未遍历、遍历过但子节点未访问完、遍历过且子节点已访问完。 } int main() { scanf("%d%d",&n,&m); while (m--) { int t1,t2; scanf("%d%d",&t1,&t2); List[t1].push_back(t2); List[t2].push_back(t1); } DFS(1,1); for (int a=1;a<=n;a++) for (int b=0;b<List[a].size();b++) if (i[a]!=i[List[a][b]]) //两个相连的节点不在同一个强连通分量中。 Sum[i[a]]++; //统计源节点的,也算是出度吧。 for (int a=1;a<=n;a++) printf("%d %d ",i[a],Sum[a]); for (int a=1;a<=n;a++) if (Sum[a]==1) //若强连通分量之间只有一条连边,那么必为桥。 Ans++; printf("%d",Ans+1>>1); //因为是无向图,所以重复了一倍。 return 0; }