图的连通_Tarjan

强连通分量

http://blog.csdn.net/xinghongduo/article/details/6195337
http://www.cnblogs.com/shadowland/p/5872257.html
http://blog.csdn.net/jeryjeryjery/article/details/52829142?locationNum=4&fps=1
https://www.byvoid.com/zht/blog/scc-tarjan/

题目

bzoj1051 缩点

被所有的牛认为受欢迎,也就意味着缩点之后,该牛所在的点的出度为0(否则其他点不可能全部通往该点)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int Maxn=10000;
 6 const int Maxe=50000;
 7 int n,e,tot=0,num=0;
 8 int top;
 9 int Cnt[Maxn+50],Outdegree[Maxn+50];
10 int Low[Maxn+50],Dfn[Maxn+50],Fir[Maxe+50],Stack[Maxn+50],Belong[Maxn+50];
11 bool Vis[Maxn+50];
12 struct Edge{
13     int u,v,next;
14 }E[Maxe+50];
15
16 int read(){
17     char ch=getchar();
18     int x=0,f=1;
19     while (ch<‘0‘||ch>‘9‘) {
20         if (ch==‘-‘) f=-1;
21         ch=getchar();
22     }
23     while (ch>=‘0‘&&ch<=‘9‘){
24         x=x*10+ch-‘0‘;
25         ch=getchar();
26     }
27     return  x*f;
28 }
29 void Insert(int x,int y){
30     tot++;
31     E[tot].u=x;
32     E[tot].v=y;
33     E[tot].next=Fir[x];
34     Fir[x]=tot;
35 }
36 void Tarjan(int u){
37     Low[u]=Dfn[u]=++tot;
38     Stack[++top]=u;
39     Vis[u]=1;
40     for (int p=Fir[u];p!=-1;p=E[p].next){
41         int v=E[p].v;
42         if (!Dfn[v]){
43             Tarjan(v);
44             Low[u]=min(Low[u],Low[v]);
45         }
46         else if (Vis[v])
47             Low[u]=min(Low[u],Dfn[v]);
48     }
49     if (Dfn[u]==Low[u]){
50         num++;
51         int v=-1;
52         while (u!=v){
53             v=Stack[top--];
54             Belong[v]=num;
55             Cnt[num]++;
56             Vis[v]=0;
57         }
58     }
59 }
60 int main(){
61     memset(Fir,-1,sizeof(Fir));
62     n=read();e=read();
63     for (int i=1;i<=e;i++){
64         int u=read(),v=read();
65         Insert(u,v);
66     }
67     memset(Low,0,sizeof(Low));
68     memset(Dfn,0,sizeof(Dfn));
69     memset(Vis,0,sizeof(Vis));
70     for (int i=1;i<=n;i++)
71       if (!Dfn[i])
72         Tarjan(i);
73     for (int i=1;i<=e;i++)
74       if (Belong[E[i].u]!=Belong[E[i].v])
75         Outdegree[Belong[E[i].u]]++;
76     int res=0,ans=0;
77     for (int i=1;i<=num;i++)
78       if (Outdegree[i]==0){
79           res++;
80           ans=i;
81       }
82     if(res==1) printf("%d\n",Cnt[ans]);
83     else printf("0\n");
84     return 0;
85 }

poj1236 缩点

题意+题解

第一问求缩点之后入度为0的点数(只要入度不为0,就可从其他点处得到软件);

第二问答案为max(入度为零的点数,出度为0的点数)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int Maxn=100;
 6 const int Maxe=10000;
 7 struct Edge{
 8     int from,u,v;
 9 }E[Maxe];
10 int n;
11 int tot_e=0,top=0,ans1,ans2,cnt=0;
12 int Fir[Maxn+50]={0},dfn[Maxn+50],low[Maxn+50],Stack[Maxn+100],Belong[Maxn+50];
13 int time=0;
14 int V[Maxn+50],Indegree[Maxn+50],Outdegree[Maxn+50];
15 int read(){
16     int x=0,f=1;
17     char ch=getchar();
18     while (ch<‘0‘||ch>‘9‘){
19         if (ch==‘-‘) f=-1;
20         ch=getchar();
21     }
22     while (ch>=‘0‘&&ch<=‘9‘){
23         x=x*10+ch-‘0‘;
24         ch=getchar();
25     }
26     return x*f;
27 }
28 void Insert(int u,int v){
29     tot_e++;
30     E[tot_e].u=u;E[tot_e].v=v;
31     E[tot_e].from=Fir[u];Fir[u]=tot_e;
32 }
33 void Tarjan(int x){
34     int y;
35     dfn[x]=low[x]=++time;
36     V[x]=1;
37     Stack[++top]=x;
38     for (int i=Fir[x];i;i=E[i].from){
39         y=E[i].v;
40         if (!V[y]){
41             Tarjan(y);
42             low[x]=min(low[x],low[y]);
43         }
44         if (V[y]==1)
45           low[x]=min(low[x],dfn[y]);
46     }
47     if (dfn[x]==low[x]){
48         cnt++;
49         do{
50             y=Stack[top--];
51             Belong[y]=cnt;V[y]=2;
52         }while (y!=x);
53     }
54 }
55 int main(){
56     n=read();
57     memset(V,0,sizeof(V));
58     for (int i=1;i<=n;i++){//build the graph
59         int j=read();
60         while(j){
61             Insert(i,j);
62             j=read();
63         }
64     }
65     for (int i=1;i<=n;i++)
66       if (!V[i])
67         Tarjan(i);
68     if (cnt==1){
69         printf("1\n0");
70         return 0;
71     }
72     for (int i=1;i<=tot_e;i++)
73       if (Belong[E[i].u]!=Belong[E[i].v]){
74           Outdegree[Belong[E[i].u]]++;
75           Indegree[Belong[E[i].v]]++;
76     }
77     ans1=ans2=0;
78     for (int i=1;i<=cnt;i++){
79       if (Indegree[i]==0) ans1++;
80       if (Outdegree[i]==0) ans2++;
81     }
82     printf("%d\n%d",ans1,max(ans1,ans2));
83     return 0;
84 }

poj3177 边双联通分量

题意+题解

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int Maxn=5000;
 6 const int Maxe=10000;
 7 struct edge{
 8     int u,v,from;
 9 }E[Maxe+100];
10 int n,e;
11 int tot=0,T=0,ccnum=0;
12 int Fir[Maxn+50],dfn[Maxn+50],low[Maxn+50],cc[Maxn+50],Degree[Maxn+50];
13 bool Is_cut[Maxn+50]={0};
14 int read(){
15     char ch=getchar();
16     int x=0,f=1;
17     while (ch<‘0‘||ch>‘9‘){
18         if (ch==‘-‘) f=-1;
19         ch=getchar();
20     }
21     while (ch>=‘0‘&&ch<=‘9‘){
22         x=x*10+ch-‘0‘;
23         ch=getchar();
24     }
25     return x*f;
26 }
27 void Insert(int x,int y){
28     tot++;
29     E[tot].u=x;E[tot].v=y;
30     E[tot].from=Fir[x];Fir[x]=tot;
31 }
32 void Tarjan(int x,int fa){
33     dfn[x]=low[x]=++T;
34     for (int i=Fir[x];i;i=E[i].from)
35       if (E[i].v!=fa){
36           int y=E[i].v;
37           if (!dfn[y]){
38               Tarjan(y,x);
39               low[x]=min(low[x],low[y]);
40               if (low[y]>dfn[x]) Is_cut[i]=1,Is_cut[i%2?i+1:i-1]=1;
41           }
42         else low[x]=min(low[x],dfn[y]);
43       }
44 }
45 void dfs(int x,int fa){
46     cc[x]=ccnum;
47     for (int i=Fir[x];i;i=E[i].from)
48       if (E[i].v!=fa&&!Is_cut[i]&&!cc[E[i].v])
49         dfs(E[i].v,x);
50 }
51 int main(){
52     n=read();e=read();
53     memset(Fir,0,sizeof(Fir));
54     for (int i=1;i<=e;i++){
55         int u=read(),v=read();
56         Insert(u,v);
57         Insert(v,u);
58     }
59     for (int i=1;i<=n;i++)
60       if (!dfn[i]) Tarjan(i,-1);
61     for (int i=1;i<=n;i++)
62       if (!cc[i]){
63         ccnum++;
64         dfs(i,-1);
65     }
66     int ans=0;
67     for (int i=1;i<=tot;i++)
68       if (cc[E[i].u]!=cc[E[i].v]){
69           Degree[cc[E[i].u]]++;
70           Degree[cc[E[i].v]]++;
71       }
72     for (int i=1;i<=ccnum;i++)
73       if (Degree[i]==2)ans++;
74     printf("%d",(ans+1)/2);
75     return 0;
76     return 0;
77 }

时间: 2024-10-22 00:30:34

图的连通_Tarjan的相关文章

poj 3352 Road Construction【边双连通求最少加多少条边使图双连通&amp;&amp;缩点】

Road Construction Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10141   Accepted: 5031 Description It's almost summer time, and that means that it's almost summer construction time! This year, the good people who are in charge of the r

?数据结构-图之强连通

数据结构-图之强连通 在一个无向图G中,若从顶点v_i到顶点v_j有路径相连(当然从v_j到v_i也一定有路径),则称v_i和v_j是连通的.如果G是有向图,那么连接v_i和v_j的路径中所有的边都必须同向.如果图中任意两点都是连通的,那么图被称作连通图.图的连通性是图的基本性质. 连通分量:无向图G的一个极大连通子图称为G的一个连通分量(或连通分支).连通图只有一个连通分量,即其自身:非连通的无向图有多个连通分量. 初级通路:通路中所有的顶点互不相同.初级通路必为简单通路,但反之不真. 强连通

求图的连通块

求连通块 Time Limit: 1sec    Memory Limit:256MB Description 输入一个简单无向图,求出图中连通块的数目. Input 输入的第一行包含两个整数n和m,n是图的顶点数,m是边数.1<=n<=100,0<=m<=10000. 以下m行,每行是一个数对u v,表示存在边(u,v).顶点编号从1开始. Output 单独一行输出连通块的数目. Sample Input 5 3 1 2 1 3 2 4 Sample Output 2 这个题目

如何判断图的连通

判断图是否连通,可用dfs和bfs遍历图算法,注意点数目较多,又是稀疏图的话,最后使用邻接表的方法存储.另外推荐采用的是并查集的方法.初始化时将每个节点看作一个集合,则每给出一条边即把两个集合合并.最后遍历所有点,有几个集合便有几个连通分量,若只有一个集合说明图连通.并查集方法通常情况下时间效率较高,还能判断一个图是否有回路,在kruskal算法中也可以使用. (1)DFS判断 int count = 0; void DFS(MGrap G. int i) { int j = 0; visite

图之强连通、强连通图、强连通分量 Tarjan算法

强连通分量 简介 在阅读下列内容之前,请务必了解图论基础部分. 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components,SCC)的定义是:极大的强连通子图. 这里想要介绍的是如何来求强连通分量. Tarjan 算法 Robert E. Tarjan (1948~) 美国人. Tarjan 发明了很多算法结构.光 Tarjan 算法就有很多,比如求各种联通分量的 Tarjan 算法,求 LCA(Lowest Comm

ACM学习-图双连通子图

// ACM学习-割点和桥.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<iostream> #include<queue> #include<vector> #include<algorithm> using namespace std; const int v = 13; int edge[v][v] = { { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0

并查集-判断图的连通

来看一个实例,杭电1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块.像畅通工程这题,问还需要修几条路,实质就是求有几个连通分支.如果是1个连通分支,说明整幅图上的点都连起来了,不用再修路了:如果是2个连通分支,则只要再修1条路,从两个分支中各选一个点,把它们连起来,那么所有的点都是连起来的了:如

图的应用之——图的连通

题目描述 给定一个图的邻接矩阵,请判断该图是否是连通图.连通图:任意两个顶点之间都有路径. --程序要求-- 若使用C++只能include一个头文件iostream:若使用C语言只能include一个头文件stdio 程序中若include多过一个头文件,不看代码,作0分处理 不允许使用第三方对象或函数实现本题的要求 输入 第1行输入一个整数k,表示有k个测试数据 第2行输入一个整数n,表示有n个结点 从第3行起到第n+2行输入一个邻接矩阵,其中Matrix[i,j]=1表示第i,j个结点之间

6_12 油田(UVa572)&lt;图的连通块DFS&gt;

有一家石油公司负责探勘某块地底下的石油含量,这块地是矩行的,并且为了探勘的方便被切割为许多小块.然后使用仪器对每个小块去探勘.含有石油的小块称为一个pocket.假如两个pocket相连,则这两个pocket属于同一个oil deposit.(所谓相连的定义与踩地雷游戏中的定义相同,请参考sample input,sample output)你的任务就是要找出这块地包含几个不同的oil deposit.Input输入包含好几组数据,每组数据的第一行有2个整数m,n.m代表这块地的列数,n代表这块