解决有向图的强连通分量的算法,有两个,一个是tarjan,一个是kosaraju,上午只看了一下kosaraju,不算太难,理解之后写了个模板题。

先说kosaraju算法,算法的主要思路是进行两次dfs,一次是正向边,一次是反向边,在时间复杂度O(V+E)之下便可统计出有多少个强连通分量以及每个点所属的强连通分量编号。

下面说一次具体实现过程及正确性,假设一副有向图G,他一定是由若干个强连通分量所构成的,这些强连通分量之间可以有边连接,但是边的方向一定是相同的,否则这两个连通分量可以合并为一个强连通分量。我们将每个scc看作一个点的话,图G就转化为了一个DAG。我们在第一次正向dfs时候对点进行逆序标记,这样的话标号最大的点一定位于这个DAG的起点,接下来将边反向,对于scc内部的点显然没影响,只是DAG的方向变了,此时从标号大的点开始搜索,能一次访问到的点一定位于同一个scc!至此算法结束。

1332 上白泽慧音

http://codevs.cn/problem/1332/

时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
 
 
 
题目描述 Description

在幻想乡,上白泽慧音是以知识渊博闻名的老师。春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点。人间之里由N个村庄(编号为1..N)和M条道路组成,道路分为两种一种为单向通行的,一种为双向通行的,分别用1和2来标记。如果存在由村庄A到达村庄B的通路,那么我们认为可以从村庄A到达村庄B,记为(A,B)。当(A,B)和(B,A)同时满足时,我们认为A,B是绝对连通的,记为<A,B>。绝对连通区域是指一个村庄的集合,在这个集合中任意两个村庄X,Y都满足<X,Y>。现在你的任务是,找出最大的绝对连通区域,并将这个绝对连通区域的村庄按编号依次输出。若存在两个最大的,输出字典序最小的,比如当存在1,3,4和2,5,6这两个最大连通区域时,输出的是1,3,4。

输入描述 Input Description

第1行:两个正整数N,M

第2..M+1行:每行三个正整数a,b,t, t = 1表示存在从村庄a到b的单向道路,t = 2表示村庄a,b之间存在双向通行的道路。保证每条道路只出现一次。

输出描述 Output Description

第1行: 1个整数,表示最大的绝对连通区域包含的村庄个数。

第2行:若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。

样例输入 Sample Input

5 5

1 2 1

1 3 2

2 4 2

5 1 2

3 5 1

样例输出 Sample Output

3

1 3 5

数据范围及提示 Data Size & Hint

对于60%的数据:N <= 200且M <= 10,000

对于100%的数据:N <= 5,000且M <= 50,000

分类标签 Tags 点此展开

 #include<bits/stdc++.h>
using namespace std;
struct Edge
{
int v,next;
}e1[],e2[];
int first1[],first2[];
int tot1,tot2;
bool vis[];
int f[];
int tot[];
vector<int>vi;
void add1(int u,int v){
e1[tot1].v=v;
e1[tot1].next=first1[u];
first1[u]=tot1++;
}
void add2(int u,int v){
e2[tot2].v=v;
e2[tot2].next=first2[u];
first2[u]=tot2++;
}
void dfs1(int u){
vis[u]=;
for(int i=first1[u];~i;i=e1[i].next){
int v=e1[i].v;
if(vis[v]) continue;
dfs1(v);
}
vi.push_back(u);
}
int dfs2(int u,int k){
vis[u]=;
f[u]=k;
int s=;
for(int i=first2[u];~i;i=e2[i].next){
int v=e2[i].v;
if(vis[v]) continue;
s+=dfs2(v,k);
}
return s;
} int main()
{
int N,M,i,j,k,u,v,t,w;
while(cin>>N>>M){
vi.clear();
memset(first1,-,sizeof(first1));
memset(first2,-,sizeof(first2));
memset(vis,,sizeof(vis));
memset(tot,,sizeof(tot));
tot1=tot2=;
for(i=;i<=M;++i){
scanf("%d%d%d",&u,&v,&t);
add1(u,v);
add2(v,u);
if(t==){
add1(v,u);
add2(u,v);
}
}
for(i=;i<=N;++i){
if(!vis[i]) dfs1(i);
}
memset(vis,,sizeof(vis));
k=;
int maxk=;
for(i=N-;i>=;--i){
if(!vis[vi[i]]) maxk=max(maxk,dfs2(vi[i],++k));
}
cout<<maxk<<endl;
for(i=;i<=N;++i) tot[f[i]]++;
for(i=;i<=N;++i){
if(maxk==tot[f[i]]) {maxk=f[i];break;}
}
for(i=;i<=N;++i){
if(f[i]==maxk){
cout<<i;
break;
}
}
i++;
for(;i<=N;++i){
if(f[i]==maxk)
printf(" %d",i);
}
puts("");
}
return ;
}

强连通分量算法-codevs1332的更多相关文章

  1. 强连通分量算法·$tarjan$初探

    嗯,今天好不容易把鸽了好久的缩点给弄完了--感觉好像--很简单? 算法的目的,其实就是在有向图上,把一个强连通分量缩成一个点--然后我们再对此搞搞事情,\(over\) 哦对,时间复杂度很显然是\(\ ...

  2. Tarjan的强连通分量算法

    Tarjan算法用于寻找图G(V,E)中的所有强连通分量,其时间复杂度为O(|V|+|E|). 所谓强连通分量就是V的某个极大子集,其中任意两个结点u,v在图中都存在一条从u到v的路径. Tarjan ...

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

    原文地址:https://blog.csdn.net/qq_16234613/article/details/77431043 一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶 ...

  4. 有向图强连通分量Tarjan算法

    在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...

  5. Tarjan算法分解强连通分量(附详细参考文章)

    Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...

  6. 模板 - 图论 - 强连通分量 - Kosaraju算法

    这个算法是自己实现的Kosaraju算法,附带一个缩点,其实缩点这个跟Kosaraju算法没有什么关系,应该其他的强连通分量算法计算出每个点所属的强连通分量之后也可以这样缩点. 算法复杂度: Kosa ...

  7. 浅析强连通分量(Tarjan和kosaraju)

    理解   在有向图G中,如果两点互相可达,则称这两个点强连通,如果G中任意两点互相可达,则称G是强连通图. 定理: 1.一个有向图是强连通的,当且仅当G中有一个回路,它至少包含每个节点一次.     ...

  8. tarjan 强连通分量

    一.强连通分量定义 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly c ...

  9. poj 2762 Going from u to v or from v to u?【强连通分量缩点+拓扑排序】

    Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15812 ...

随机推荐

  1. select 自动选择 检查下拉列表

    下面我们来看一下selenium webdriver是如何来处理select下拉框的,以Apple注册页面为例. https://appleid.apple.com/cgi-bin/WebObject ...

  2. hbase(一)

    1.hbase安装参考 http://blog.csdn.net/wild46cat/article/details/53214159 2.遇到的问题: ERROR: The node /hbase ...

  3. 127. Word Ladder(单词变换 广度优先)

    Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest t ...

  4. 2018秦皇岛ccpc-camp Steins;Gate (原根+FFT)

    因为给定的模数P保证是素数,所以P一定有原根. 根据原根的性质,若\(g\)是\(P\)的原根,则\(g^k\)能够生成\([1,P-1]\)中所有的数,这样的k一共有P-2个. 则\(a_i*a_j ...

  5. Java应用开发中的SQL注入攻击

    1. 什么是SQL注入攻击? SQL注入攻击是黑客对数据库进行攻击的常用手段之一.随着B/S模式应用开发的发展,使用这种模式编写应用程序的程序员越来越多.但是由于程序员的水平及经验参差不齐,相当一部分 ...

  6. Ubuntu 16.04 安装Postman

    Ubuntu 16.04 安装Postman: 1.官网下载地址:https://www.getpostman.com/根据机器类型选择64位下载. 2.进入下载目录,解压该文件sudo tar -x ...

  7. python中统计计数的几种方法

    以下实例展示了 count() 方法的使用方法: 1 2 3 4 5 6 # !/usr/bin/python3   T = (123, 'Google', 'Runoob', 'Taobao', 1 ...

  8. Java硬件同步机制Swap指令模拟+记录型信号量模拟

    学校实验存档//.. 以经典的生产者消费者问题作为背景. 进程同步方式接口: package method; /** * P表示通过,V表示释放 */ public interface Method ...

  9. centos7安装kvm环境采用网桥模式并创建虚拟机制作openstack需要的镜像

    初始环境的安装:centos7 mini iso镜像进行安装的系统 采用的环境是vm该软件,联网方式NAT模式下配置的静态ip(如何在NAT模式下配置静态ip参考之前的文章) 1.由于要安装kvm环境 ...

  10. 利用python获取nginx服务的ip以及流量统计信息

    #!/usr/bin/python #coding=utf8 log_file = "/usr/local/nginx/logs/access.log" with open(log ...