51nod1076(tarjan)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1076

题意:中文题诶~

思路:先用tarjan找出所有桥,再用桥限制的情况下dfs一遍。。。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 const int MAXN=1e5+10;
 5 vector<int> mp[MAXN];
 6 bool is_cut[MAXN];
 7 int n, m, ans=0;
 8 int vis[MAXN];
 9 int low[MAXN], dfn[MAXN], pre[MAXN];//pre[u]记录u的父亲节点编号
10 //dfn[u]记录节点u在DFS过程中被遍历到的次序号,low[u]记录节点u或u的子树通过非父子边追溯到最早的祖先节点(即DFS次序号最小
11
12 void tarjan(int u, int fu){
13     pre[u]=fu;//记录当前u的父亲节点
14     dfn[u]=low[u]=++ans;
15     for(int i=0; i<mp[u].size(); i++){
16         int v=mp[u][i];
17         if(!dfn[v]){
18             tarjan(v, u);
19             low[u]=min(low[u], low[v]);
20         }else if(fu!=v){//如果v是u的父亲的话,即有重边,那么不可能是桥
21             low[u]=min(low[u], dfn[v]);
22         }
23     }
24 }
25
26 void dfs(int x, int cnt){
27     vis[x]=cnt;
28     for(int i=0; i<mp[x].size(); i++){
29         int v=mp[x][i];
30         if(vis[v]||is_cut[v]&&is_cut[x]) continue;
31         dfs(v, cnt);
32     }
33 }
34
35 void solve(void){
36     for(int i=1; i<=n; i++){
37         if(!dfn[i]) tarjan(i, 0);
38         int v=pre[i];
39         if(dfn[v]<low[i]&&v>0){
40             is_cut[i]=is_cut[v]=1;
41         }
42     }
43     int cnt=0;
44     for(int i=1; i<=n; i++){
45         if(!vis[i]){
46             cnt++;
47             dfs(i, cnt);
48         }
49     }
50 }
51
52 int main(void){
53     scanf("%d%d", &n, &m);
54     for(int i=0; i<m; i++){
55         int x, y;
56         scanf("%d%d", &x, &y);
57         mp[x].push_back(y);
58         mp[y].push_back(x);
59     }
60     solve();
61     int q;
62     scanf("%d", &q);
63     while(q--){
64         int s, e;
65         scanf("%d%d", &s, &e);
66         if(vis[s]==vis[e]) puts("Yes");
67         else puts("No");
68     }
69     return 0;
70 }

时间: 2024-10-12 03:54:39

51nod1076(tarjan)的相关文章

有向图强连通分支的Tarjan算法讲解 + HDU 1269 连通图 Tarjan 结题报告

题目很简单就拿着这道题简单说说 有向图强连通分支的Tarjan算法 有向图强连通分支的Tarjan算法伪代码如下:void Tarjan(u) {dfn[u]=low[u]=++index//进行DFS,每发现一个新的点就对这个点打上时间戳,所以先找到的点时间戳越早,dfn[U]表示最早发现u的时间,low[u]表示u能到达的最早的时间戳.stack.push(u)//将U压入栈中for each (u, v) in E {if (v is not visted)//如果V点没有经历过DFS,则

【LCA/tarjan】POJ1470-Closest Common Ancestors

[题意] 给出一棵树和多组查询,求以每个节点为LCA的查询数有多少? [错误点] ①读入的时候,注意它的空格是随意的呀!一开始不知道怎么弄,后来看了DISCUSS区大神的话: 询问部分输入: scanf("%d",&m); for(int i=0;i<m;i++){ scanf(" (%d %d)",&a,&b); } 注意scanf(" 这里有一个空格 ②多组数据啊!注意这句话:The input file contents

tarjan强连通图分量

[有向图强连通分量] 有向图强连通分量的Tarjan算法 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components). 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达.{5},{6}也分别是两个强连通分量. [Tarjan算法] Tarjan算法是基于对图深

POJ 1236 tarjan

Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19613   Accepted: 7725 Description A number of schools are connected to a computer network. Agreements have been developed among those schools: each school maintains a li

【最近公共祖先Tarjan】Tarjan求LCA练习

Tarjan求LCA 这是一篇非常好的讲解,靠这个文章搞懂的~ 1 void tarjan(int u) 2 { 3 vis[u]=1; 4 for(int i=0;i<edge[u].size();i++) 5 { 6 int v=edge[u][i]; 7 if(vis[v] == 0) 8 { 9 tarjan(v); 10 p[v]=u; 11 } 12 } 13 for(int i=0;i<qy[u].size();i++) 14 { 15 int v=qy[u][i].v,id=q

UVa 12587 Reduce the Maintenance Cost(Tarjan + 二分 + DFS)

题意:n个城市(n <= 10000), 有m条边(m <= 40000),每一个城市有一个维护费用Cost(i),除此之外,每条边的维修费用为去掉该边后不能通信的城市对数与边权的积.这个费用要加到这条边的两端城市的某一个,问你全部城市的最大费用的最小值.. 思路:首先边的费用能够通过Tarjan求桥之后求得(利用桥的性质),然后就是二分答案了!对于每一个点,假设有个儿子不能维护.那么不可行,否则.试着让儿子去维护边权,假设不可行,仅仅能让父亲承担. #include <iostream

hdu 2586(Tarjan 离线算法)

How far away ?                                                                             Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)                                                                            

【转】BYV--有向图强连通分量的Tarjan算法

转自beyond the void 的博客: https://www.byvoid.com/zhs/blog/scc-tarjan 注:红色为标注部分 [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components). 下图中,子图{1,2,3,4}为一个强连通分量,因为顶

【学习整理】Tarjan:强连通分量+割点+割边

Tarjan求强连通分量 在一个有向图中,如果某两点间都有互相到达的路径,那么称中两个点强联通,如果任意两点都强联通,那么称这个图为强联通图:一个有向图的极大强联通子图称为强联通分量.   算法可以在 的时间内求出一个图的所有强联通分量. 表示进入结点 的时间 表示从 所能追溯到的栈中点的最早时间 如果某个点 已经在栈中则更新  否则对 进行回溯,并在回溯后更新  #include<iostream> #include<cstdlib> #include<cstdio>