强连通分量算法-codevs1332
解决有向图的强连通分量的算法,有两个,一个是tarjan,一个是kosaraju,上午只看了一下kosaraju,不算太难,理解之后写了个模板题。
先说kosaraju算法,算法的主要思路是进行两次dfs,一次是正向边,一次是反向边,在时间复杂度O(V+E)之下便可统计出有多少个强连通分量以及每个点所属的强连通分量编号。
下面说一次具体实现过程及正确性,假设一副有向图G,他一定是由若干个强连通分量所构成的,这些强连通分量之间可以有边连接,但是边的方向一定是相同的,否则这两个连通分量可以合并为一个强连通分量。我们将每个scc看作一个点的话,图G就转化为了一个DAG。我们在第一次正向dfs时候对点进行逆序标记,这样的话标号最大的点一定位于这个DAG的起点,接下来将边反向,对于scc内部的点显然没影响,只是DAG的方向变了,此时从标号大的点开始搜索,能一次访问到的点一定位于同一个scc!至此算法结束。

1332 上白泽慧音
在幻想乡,上白泽慧音是以知识渊博闻名的老师。春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄。因此慧音决定换一个能够聚集最多人数的村庄作为新的教学地点。人间之里由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。
第1行:两个正整数N,M
第2..M+1行:每行三个正整数a,b,t, t = 1表示存在从村庄a到b的单向道路,t = 2表示村庄a,b之间存在双向通行的道路。保证每条道路只出现一次。
第1行: 1个整数,表示最大的绝对连通区域包含的村庄个数。
第2行:若干个整数,依次输出最大的绝对连通区域所包含的村庄编号。
5 5
1 2 1
1 3 2
2 4 2
5 1 2
3 5 1
3
1 3 5
对于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的更多相关文章
- 强连通分量算法·$tarjan$初探
嗯,今天好不容易把鸽了好久的缩点给弄完了--感觉好像--很简单? 算法的目的,其实就是在有向图上,把一个强连通分量缩成一个点--然后我们再对此搞搞事情,\(over\) 哦对,时间复杂度很显然是\(\ ...
- Tarjan的强连通分量算法
Tarjan算法用于寻找图G(V,E)中的所有强连通分量,其时间复杂度为O(|V|+|E|). 所谓强连通分量就是V的某个极大子集,其中任意两个结点u,v在图中都存在一条从u到v的路径. Tarjan ...
- 图之强连通、强连通图、强连通分量 Tarjan算法
原文地址:https://blog.csdn.net/qq_16234613/article/details/77431043 一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶 ...
- 有向图强连通分量Tarjan算法
在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...
- Tarjan算法分解强连通分量(附详细参考文章)
Tarjan算法分解强连通分量 算法思路: 算法通过dfs遍历整个连通分量,并在遍历过程中给每个点打上两个记号:一个是时间戳,即首次访问到节点i的时刻,另一个是节点u的某一个祖先被访问的最早时刻. 时 ...
- 模板 - 图论 - 强连通分量 - Kosaraju算法
这个算法是自己实现的Kosaraju算法,附带一个缩点,其实缩点这个跟Kosaraju算法没有什么关系,应该其他的强连通分量算法计算出每个点所属的强连通分量之后也可以这样缩点. 算法复杂度: Kosa ...
- 浅析强连通分量(Tarjan和kosaraju)
理解 在有向图G中,如果两点互相可达,则称这两个点强连通,如果G中任意两点互相可达,则称G是强连通图. 定理: 1.一个有向图是强连通的,当且仅当G中有一个回路,它至少包含每个节点一次. ...
- tarjan 强连通分量
一.强连通分量定义 有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly c ...
- 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 ...
随机推荐
- 20165324 《Java程序设计》 第六周
学号 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 第八章 常用实用类 String类 构造String对象:常量对象:String对象:引用String常 ...
- 150. Evaluate Reverse Polish Notation(逆波兰表达式)
Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...
- sgu 103 Traffic Lights 解题报告及测试数据
103. Traffic Lights Time limit per test: 0.25 second(s) Memory limit: 4096 kilobytes 题解: 1.其实就是求两点间的 ...
- spark[源码]-Pool分析
概述 这篇文章主要是分析一下Pool这个任务调度的队列.整体代码量也不是很大,正好可以详细的分析一下,前面在TaskSchedulerImpl提到大体的功能,这个点在丰富一下吧. DAGSchedul ...
- Scala List 用法
1.++[B] 在A元素后面追加B元素 scala> val a = List(1) a: List[Int] = List(1) scala> val b = List(2) b: ...
- Web前端页面的浏览器兼容性测试心得(三)总结一些IE8兼容问题的解决方案
由于IE8不支持HTML5,而它又是Win7的默认浏览器,我们即使讨厌它,在这几年却也拿它没办法. 最近做了个需要兼容IE8的项目,不可避免地用了HTML5+CSS3,甚至canvas和svg,做兼容 ...
- netbeans许可证模板设置
工具->模板->设置 user=your name 工具->模板->许可证->默认许可证 <#if licenseFirst??>${licenseFirst ...
- 3.1、Ubuntu系统中jmeter的安装和目录解析
以下内容亲测,如果不对的地方,欢迎留言指正,不甚感激.^_^祝工作愉快^_^ Jmeter是一个非常好用的压力测试工具. Jmeter用来做轻量级的压力测试,非常合适,只需要十几分钟,就能把压力测 ...
- HTML DOM setInterval() 方法
定义和用法 setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被 ...
- 国光大力推荐(安利)Deepin15.4
简介 深度操作系统15.4 Beta(deepin15.4)相比deepin15.3来看,外观上要更加优雅.现在还在内测中,相信不就官网就会发布正式版.小子昨天下午删了我的windows10,特意来尝 ...