强连通分量--tarjan算法
今天学了一个强连通分量,用tarjan做。北京之前讲过,今天讲完和之前一样,没有什么进步。上课没听讲,只好回来搞,这里安利一个博客:链接
https://blog.csdn.net/qq_34374664/article/details/77488976
讲一下我自己的体会吧,其实就是维护一个栈,然后树上跑dfs,每个节点存两个值:dn和low,dn代表dfs的顺序(时间),low代表的是他可以连通的最小的节点。
模拟一下,然后就会发现,其实整个算法就是模拟了一下将每个点压入栈。然后遇到之前在栈里的元素,向后弹出到这一位就行了。
洛谷板子题:链接
直接上代码,很好懂。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int m,n,len = ,stc[];
int ri = ,tot = ,ans = ;
int num[];
struct node{
int l,r,nxt;
}a[];
int low[],lst[];
int dn[];
int chu[];
bool vis[];
int add(int x,int y)
{
a[++len].l = x;
a[len].r = y;
a[len].nxt = lst[x];
lst[x] = len;
chu[x]++;
}
void dfs(int x)
{
dn[x] = low[x] = ++tot;
stc[++ri] = x;
vis[x] = ;
for(int k = lst[x];k;k = a[k].nxt)
{
int y = a[k].r;
if(!dn[y])
{
dfs(y);
low[x] = min(low[x],low[y]);
}
else if(vis[y])
{
low[x] = min(low[x],dn[y]);
}
}
if(low[x] == dn[x])
{
ans ++;
int v;
do
{
num[ans]++;
vis[stc[ri]] = ;
v = stc[ri--];
}
while(x != v);
}
}
int main()
{
memset(vis,,sizeof(vis));
scanf("%d%d",&n,&m);
int x,y;
for(int i = ;i <= m;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i = ;i <= n;i++)
if(dn[i] == )
{
dfs(i);
}
// cout<<ans<<endl;
tot = ;
for(int i = ;i <= ans;i++)
{
if(num[i] > )
{
tot++;
}
}
printf("%d\n",tot);
return ;
}
洛谷日推了一道题,也是板子,写一下:
每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜 欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你 算出有多少头奶牛可以当明星。
输入输出格式
输入格式: 第一行:两个用空格分开的整数:N和M 第二行到第M + 1行:每行两个用空格分开的整数:A和B,表示A喜欢B 输出格式: 第一行:单独一个整数,表示明星奶牛的数量 输入输出样例
输入样例#: 复制 输出样例#: 复制
直接上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(),c < '' || c > '')
if(c == '-' ) op = ;
x = c - '';
while(c = getchar(),c >= '' && c <= '')
x =x * + c - '';
if(op)
x = -x;
}
int lst[],dfn[],low[],n,m,tot = ,str[],top = ,vis[];
int num[],chu[],col[],len,ans;
struct node{
int l,r,nxt;
}a[];
void add(int x,int y)
{
a[++len].l = x;
a[len].r = y;
a[len].nxt = lst[x];
lst[x] =len;
// chu[x]++;
}
void tarjan(int x)
{
dfn[x] = low[x] = ++tot;
str[++top] = x;
vis[x] = ;
for(int k = lst[x];k;k = a[k].nxt)
{
int y = a[k].r;
if(!dfn[y])
{
tarjan(y);
low[x] = min(low[x],low[y]);
}
else if(vis[y])
{
low[x] = min(low[x],dfn[y]);
}
}
if(low[x] == dfn[x])
{
ans++;
int v;
do
{
num[ans]++;
vis[str[top]] = ;
v = str[top--];
col[v] = ans;
}
while(x != v);
}
}
int main()
{
read(n);read(m);
for(int i = ;i <= m;i++)
{
int x,y;
read(x);read(y);
add(x,y);
}
for(int i = ;i <= n;i++)
{
if(dfn[i] == )
{
tarjan(i);
}
}
for(int i = ;i <= n;i++)
{
for(int k = lst[i];k;k = a[k].nxt)
{
if(col[a[k].l] != col[a[k].r])
{
chu[col[a[k].l]]++;
}
}
}
int tot= ,f;
for(int i = ;i <= ans;i++)
{
if(chu[i] == )
{
tot++;
f = i;
}
if(tot >= )
{
puts("");
return ;
}
}
printf("%d\n",num[f]);
return ;
}
强连通分量--tarjan算法的更多相关文章
- 有向图强连通分量Tarjan算法
在https://www.byvoid.com/zhs/blog/scc-tarjan中关于Tarjan算法的描述非常好,转述如下: 首先解释几个概念: 有向图强连通分量:在有向图G中,如果两个顶点间 ...
- 有向图强连通分量 Tarjan算法
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极 ...
- [有向图的强连通分量][Tarjan算法]
https://www.byvoid.com/blog/scc-tarjan 主要思想 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的 ...
- 图之强连通、强连通图、强连通分量 Tarjan算法
原文地址:https://blog.csdn.net/qq_16234613/article/details/77431043 一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶 ...
- 图论-强连通分量-Tarjan算法
有关概念: 如果图中两个结点可以相互通达,则称两个结点强连通. 如果有向图G的每两个结点都强连通,称G是一个强连通图. 有向图的极大强连通子图(没有被其他强连通子图包含),称为强连通分量.(这个定义在 ...
- 求图的强连通分量--tarjan算法
一:tarjan算法详解 ◦思想: ◦ ◦做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间 ...
- POJ1236_A - Network of Schools _强连通分量::Tarjan算法
Time Limit: 1000MS Memory Limit: 10000K Description A number of schools are connected to a compute ...
- poj 2186 Popular Cows 【强连通分量Tarjan算法 + 树问题】
题目地址:http://poj.org/problem?id=2186 Popular Cows Time Limit: 2000MS Memory Limit: 65536K Total Sub ...
- 强连通分量——tarjan算法
概念: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通.如果有向图G的每两个顶点都强连 ...
随机推荐
- Java 基础入门随笔(2) JavaSE版——关键字、进制转换、类型转换
1.Java语言-关键字 关键字:被java语言赋予了特殊含义的词,特点是所有的字母都为小写. java涉及到的关键字整理: 用于定义数据类型的关键字 class interface byte sho ...
- GridView中的日期处理
数字 {0:N2} 12.36 数字 {0:N0} 13 货币 {0:c2} $12.36 货币 {0:c4} $12.3656 货币 "¥{0:N2}" ¥12.36 ...
- PHP 之phpqrcode类库生成二维码
<?php /** * Created by PhpStorm. * User: 25754 * Date: 2019/6/4 * Time: 15:53 */ include "./ ...
- EF-Lamdba
一丶基本语法 var userList=db.set<table>().where(c=>c.id=="001"&&c.userName.Cont ...
- Day 13 进程和线程
进程和线程 今天我们使用的计算机早已进入多CPU或多核时代,而我们使用的操作系统都是支持“多任务”的操作系统,这使得我们可以同时运行多个程序,也可以将一个程序分解为若干个相对独立的子任务,让多个子任务 ...
- ZOJ 3180 Number Game(模拟,倒推)
题目 思路: 先倒推!到最后第二步,然后: 初始状态不一定满足这个状态.所以我们要先从初始状态构造出它出发的三种状态.那这三种状态跟倒推得到的状态比较即可. #include<stdio.h&g ...
- 11.best fields策略(dis_max参数设置)
主要知识点 常规multi-field搜索结果分析 dis_max参数设置 一.为帖子数据增加content字段 POST /forum/article/_bulk { "u ...
- 强悍的 ubuntu —— 命令行访问网页
所谓以命令行的方式访问网页,即是在终端下以文本的形式访问网站,这里推荐一个工具:w3m, $ sudo apt-get install w3m $ w3m www.baidu.com
- 【Codeforces 467C】George and Job
[链接] 我是链接,点我呀:) [题意] 让你从1..n这n个数字中 选出来k个不相交的长度为m的区间 然后这个k个区间的和最大 求出这k个区间的和的最大值 [题解] 设dp[i][j]表示前i个数字 ...
- npm install socket.io 提示缺少"VCBuild.exe"
http://www.cnblogs.com/yangzhx/p/4648501.html https://www.v2ex.com/t/120493