解决有向图的强连通分量的算法,有两个,一个是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. log4j相关配置

    1.概述         log4j是Apache提供的一个日志实现,可以用于我们项目中的日志记录,有log4j1和log4j2两个版本,本文使用log4j2这个版本.SLF4J(Simple log ...

  2. OpenStack的架构详解

    OpenStack既是一个社区,也是一个项目和一个开源软件,它提供了一个部署云的操作平台或工具集.其宗旨在于,帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云,也为大云.小云提供可扩展的.灵活的 ...

  3. netty7---自定义序列化接口

    package com.cn.core; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.util.Ar ...

  4. Spring事务回滚

    配置事物: @Configuration /**强制使用cglib代理时就把proxy-target-class设为true.*/ @EnableTransactionManagement(proxy ...

  5. LSTM java 实现

    由于实验室事情缘故,需要将Python写的神经网络转成Java版本的,但是python中的numpy等啥包也不知道在Java里面对应的是什么工具,所以索性直接寻找一个现成可用的Java神经网络框架,于 ...

  6. KALI视频学习11-15

    KALI视频学习11-15 第十一集 看到openvas的主界面(web界面) ping靶机,看是否能正常连通 创建一个扫描目标Configuration-Targets,默认扫描目标为本机 添加一个 ...

  7. uboot下ext4load的用法

    将sd卡的某个分区下的某个目录里的某个文件加载到内存的某个地址,示例如下: ext4load mmc 0:1 0xa0000000 /bin/vi

  8. OpenDayLight "Error executing command: java.lang.NullPointerException"问题解决

    参考: Fedora 21 mostly working but NullPointerException at Karaf shell 在使用ODL的时候,安装功能组件时出现: Error exec ...

  9. kubectl delete

    kubectl delete 通过配置文件名.stdin.资源名称或label选择器来删除资源. 支持JSON和YAML格式文件.可以只指定一种类型的参数:文件名.资源名称或label选择器. 有些资 ...

  10. How to implement multiple constructor with different parameters in Scala

    Using scala is just another road, and it just like we fall in love again, but there is some pain you ...