tarjan 强联通分量和割点

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<ctime>
 5 #include<iostream>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<stack>
 9 #include<set>
10 #define esp (1e-6)
11 #define inf (0x3f3f3f3f)
12 #define l(a) ((a)<<1)
13 #define r(a) ((a)<<1|1)
14 #define b(a) (1<<(a))
15 #define rep(i,a,b) for(int i=a;i<=(b);i++)
16 #define clr(a) memset(a,0,sizeof(a))
17 typedef long long ll;
18 typedef unsigned long long ull;
19 using namespace std;
20 int readint(){
21     int t=0,f=1;char c=getchar();
22     while(!isdigit(c)){
23         if(c==‘-‘) f=-1;
24         c=getchar();
25     }
26     while(isdigit(c)){
27         t=(t<<3)+(t<<1)+c-‘0‘;
28         c=getchar();
29     }
30     return t*f;
31 }
32 const int maxn=100009,maxm=200009;
33 struct edge{
34     int v;
35     edge*next;
36 }e[maxm],*pt=e,*fir[maxn];
37 int n,m,ans,dfstime,scccnt,size[maxn],pre[maxn],low[maxn],scc[maxn];
38 bool p[maxn];
39 void add(int u,int v){
40     pt->v=v;pt->next=fir[u];
41     fir[u]=pt++;
42 }
43 void addedge(int u,int v){
44     add(u,v);add(v,u);
45 }
46 stack<int>S;
47 void dfs(int x,int f){
48     int son=0;
49     pre[x]=low[x]=++dfstime;S.push(x);
50     for(edge*e=fir[x];e;e=e->next) if(e->v!=f){
51         if(!pre[e->v]){
52             son++;dfs(e->v,x);
53             low[x]=min(low[x],low[e->v]);
54             if(f!=-1&&low[e->v]>=pre[x]) p[x]=1;
55         }else if(!scc[e->v]) low[x]=min(low[x],pre[e->v]);
56     }
57     if(f==-1&&son>1) if(!p[x]) p[x]=1;
58     if(pre[x]==low[x]){
59         int t=-1;++scccnt;
60         while(t!=x){
61             t=S.top();S.pop();
62             scc[t]=scccnt;size[scccnt]++;
63         }
64     }
65 }
66 void tarjan(){
67     rep(i,1,n) if(!scc[i]) dfs(i,-1);
68     rep(i,1,n) if(p[i]) ans++;
69     cout<<ans<<endl;
70     rep(i,1,n) if(p[i]){
71         ans--;printf("%d",i);
72         putchar(ans?‘ ‘:‘\n‘);
73     }
74 }
75 int main(){
76     //freopen("#input.txt","r",stdin);
77     //freopen("#output.txt","w",stdout);
78     n=readint();m=readint();
79     rep(i,1,m){
80         int U=readint(),V=readint();
81         addedge(U,V);
82     }
83     tarjan();
84     //fclose(stdin);
85     //fclose(stdout);
86     return 0;
87 }

时间: 2024-10-12 23:54:31

tarjan 强联通分量和割点的相关文章

Tarjan强联通分量【模板】

1 #include <algorithm> 2 #include <cstdio> 3 4 using namespace std; 5 6 const int N(100015); 7 int n,m,v,u; 8 int edgesum,head[N]; 9 10 struct Edge 11 { 12 int from,to,next; 13 Edge(int from=0,int to=0,int next=0) : 14 from(from),to(to),next(n

tarjan算法求强联通分量

昨天学到了一个新的算法tarjan算法,感觉最近都没有怎么学习了...(最近有个感悟啊,就是学习一定的通过实践来进步的. 现在才明白为什么高中的时候老师强调一定要刷题,当然刷完题目之后的总结也非常地重要! 这个tarjan算法用来求强联通分量,在网上看了几篇blog,然后做了一个题目,感觉这个算法很nice啊... 如果没有学这个算法, 我肯定会想直接dfs吧orz... dfs看看是不是每个点能到达连通分量的其他点,好像这样非常麻烦啊,还要记录这个点从哪里来的...这样一想,好像直接dfs我做

Tarjan的强联通分量

求强联通分量有很多种. <C++信息学奥赛一本通>  中讲过一个dfs求强联通分量的算法Kosdaraju,为了骗字数我就待会简单的说说.然而我们这篇文章的主体是Tarjan,所以我肯定说完之后再赞扬一下Tarjan大法好是不是 首先我们讲一下强联通分量 强联通分量指的是图的一个子图.在这个子图中,任意两个节点都可以互相到达.从定义上我们就可以看出是一个有向图来,因为任意一个无向图都符合该定义. 而它的标准定义是:有向图中任意两点都联通的最大子图. 咳咳,首先庆祝一下哈--本人博客的第一张图.

HDU 1269 迷宫城堡 (强联通分量,Tarjan算法)

Problem Description: 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以通过这个通道由A房间到达B房间,但并不说明通过它可以由B房间到达A房间.Gardon需要请你写个程序确认一下是否任意两个房间都是相互连通的,即:对于任意的i和j,至少存在一条路径可以从房间i到房间j,也存在一条路径可以从房间j到房间i. Input: 输入包含多组数据

bzoj 2438: [中山市选2011]杀人游戏 (强联通分量 Tarjan)

Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Input 第一行有两个整数 N,M. 接下来有 M 行,每行两个整数 x

codevs 2822 爱在心中 tarjan(强联通分量)

2822 爱在心中 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description “每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动.爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home.” 在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况).爱是具有传递性的,即如果A爱B,B爱C,则A也爱C.如果有这样一部分人,他们彼此都相爱,则他们就超越了一

USACO06JAN The Cow Prom /// tarjan求强联通分量 oj24219

题目大意: n个点 m条边的图 求大小大于1的强联通分量的个数 https://www.cnblogs.com/stxy-ferryman/p/7779347.html tarjan求完强联通分量并染色后 计算一下每种颜色的个数 就是每个强联通块的大小 #include <stdio.h> #include <cstring> #include <algorithm> #include <stack> using namespace std; const i

HDU 1269 迷宫城堡 【强联通分量(模版题)】

知识讲解: 在代码里我们是围绕 low 和 dfn 来进行DFS,所以我们务必明白 low 和 dfn 是干什么的? 有什么用,这样才能掌握他. 1.  dfn[]  遍历到这个点的时间 2.  low[]  遍历到这个所能连接到的最短时间,说明那个最短时间可以遍历带他,他也可以走到那个最短时间. 3.  我们每次出栈的点就是一个强联通分量(这里建议观看一下课件里面的Tarjan求强联通算法的模拟过程). #include<cstdio> #include<cstdlib> #in

Light OJ 1034 - Hit the Light Switches(强联通分量)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1034 题目大意:有n盏灯,有m个关系, 关系a,b表示如果a灯开关打开那么b灯也会亮起来, 现在求至少需要打开多少开关使所有灯都亮. 题目思路:先由强联通分量缩点, 得到DAG图, 然后根据DAG图,求出有多少入度为0的点, 即为所求. 代码如下: #include<bits/stdc++.h> using namespace std; const int N = 1000