因为最近在学2sat,需要学习前置技能—Tarjan算法,所以花了一天的时间学习这个算法

算法步骤:

1.从一个点开始dfs,并加入栈

2.如果下一个点没有到过,跳到第一步

3.如果下一个点到过,并且在栈中,下一个点到这个点,这一段构成一个回路,也就是可以缩点

具体实现

void dfs(int x)
{
st.push(x); //加入栈
dis[x]=1; //x点在栈中
dfn[x]=low[x]=++te; //dfn用来表示某个点访问过,并且记录初始的low值
for(int i=f[x]; i; i=nex[i])
{
int v=to[i];
if(dfn[v]==0)
{
dfs(v);
low[x]=min(low[x],low[v]); //将一个回路的low改成一样的
}
else if(dis[v]==1)low[x]=min(low[x],low[v]); //下一个点在栈中,那么找到一个回路,但是可能是嵌套回路,所以取最小low
}
if(dfn[x]==low[x]) //表示x点的初始值没有被改变,构成一个强连通分量
{
while(st.size())
{
int g=st.top();
st.pop();
dis[g]=0;
id[g]=x; //用x命名强连通分量
if(g==x)break; //代表g是强连通分量的最后一个数
}
}
}

题目:poj2186

题解:先缩点,然后构成一个新的图,找到出度为一的一个被缩过的点,返回这个点的数量,如果有1个以上被缩过的点出度为0,那么返回0

 #include <cstdio>
#include <iostream>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <stack>
using namespace std;
#define ll long long
const int maxn=1e4+;
const int maxm=5e4+;
int f[maxn],nex[maxm],to[maxm],cnt,ot[maxm];
int dfn[maxn],low[maxn],id[maxn],te;
vector<int>ve;
stack<int>st;
int ma[maxn];
bool dis[maxn];
void add(int a,int b)
{
cnt++;
to[cnt]=b;
nex[cnt]=f[a];
f[a]=cnt;
ot[cnt]=a;
}
void dfs(int x)
{
st.push(x);
dis[x]=;
dfn[x]=low[x]=++te;
for(int i=f[x]; i; i=nex[i])
{
int v=to[i];
if(dfn[v]==)
{
dfs(v);
low[x]=min(low[x],low[v]);
}
else if(dis[v]==)low[x]=min(low[x],low[v]);
}
if(dfn[x]==low[x])
{
ve.push_back(x);
while(st.size())
{
int g=st.top();
st.pop();
dis[g]=;
id[g]=x;
if(g==x)break;
}
}
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=; i<=n; i++)id[i]=i;
for(int i=; i<=m; i++)
{
int a,b;
scanf("%d %d",&a,&b);
add(a,b);
}
for(int i=; i<=n; i++)
if(dfn[i]==)dfs(i);
for(int i=; i<=cnt; i++)
{
int a=id[to[i]];
int b=id[ot[i]];
if(a!=b)
ma[b]++;
}
int fla=,num=; for(int i=; i<ve.size(); i++)
{
if(ma[ve[i]]==)num++,fla=ve[i];
}
if(ve.size()==)num=,fla=ve[];
if(num==)
{
int ans=;
for(int i=; i<=n; i++)
if(id[i]==fla)ans++;
printf("%d\n",ans);
}
else
printf("0\n");
return ;
}

Tarjan算法(缩点)的更多相关文章

  1. tarjan算法+缩点--cojs 908. 校园网

    cojs 908. 校园网 ★★   输入文件:schlnet.in   输出文件:schlnet.out   简单对比时间限制:1 s   内存限制:128 MB USACO/schlnet(译 b ...

  2. tarjan算法+缩点:求强连通分量 POJ 2186

    强连通分量:1309. [HAOI2006]受欢迎的牛 ★★   输入文件:cow.in   输出文件:cow.out   简单对比时间限制:1 s   内存限制:128 MB [题目描述] 每一头牛 ...

  3. POJ 1236 Network of Schools (tarjan算法+缩点)

    思路:使用tarjan求强连通分量并进行缩点,判断所有入度为0的点,这个点就是必须要给予文件的点,分别计算出度,入度为零的点的个数,取二者的最大值就是把这个图变成强连通需要加的边数. 一个取值需要讨论 ...

  4. POJ - 2553 tarjan算法+缩点

    题意: 给你n个点,和m条单向边,问你有多少点满足(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}关系,并把这些点输出(要注意的是这个关系中是蕴含关系而不是且(&&)关系) 题解: ...

  5. tarjan算法(求强连通子块,缩点)

    tarjan算法求图中的强连通子图的个数. #include<iostream> #include<stack> #include<queue> #include& ...

  6. poj2186tarjan算法缩点求出度

    poj2186tarjan算法缩点求出度 自己打一遍第一题,入门啦,入门啦 题目还算简单,多头牛,给你仰慕关系(可传递),问你最后有没有牛被所有的牛仰慕 根据关系可以建图,利用tarjan算法缩点处理 ...

  7. Tarjan算法求割点

    (声明:以下图片来源于网络) Tarjan算法求出割点个数 首先来了解什么是连通图 在图论中,连通图基于连通的概念.在一个无向图 G 中,若从顶点i到顶点j有路径相连(当然从j到i也一定有路径),则称 ...

  8. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  9. tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)

    这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...

随机推荐

  1. Java中的生产消费者问题

    package day190109; import java.util.LinkedList; import java.util.Queue; import java.util.Random; pub ...

  2. visual studio 启动无法打开IIS express

    删除 解决方案下的vs文件夹之后重新生成

  3. c/c++ 线性表之双向循环链表

    c/c++ 线性表之双向循环链表 线性表之双向循环链表 不是存放在连续的内存空间,链表中的每个节点的next都指向下一个节点,每个节点的before都指向前一个节点,最后一个节点的下一个节点不是NUL ...

  4. MySQL用户远程登录问题

    今天来水一篇,差点被这个远程登录搞死了,所以记录下这个问题. 先使用status命令查看一下MySQL版本,这里可以可以看到我用的是是8.0.12版本. mysql> status ------ ...

  5. Pycharm用鼠标滚轮控制字体大小

    一.pycharm字体放大的设置 File —> setting —> Keymap —>在搜寻框中输入:increase —> Increase Font Size(双击) ...

  6. CSS鼠标悬浮DIV后显示DIV外的按钮

    昨天写样式遇到个问题,如何让鼠标悬浮DIV后,显示DIV外的按钮,可以点击到按钮. 效果如下: 问题: 在DIV hover时候将按钮设为display: block,这是很直接的想法,但是这有个问题 ...

  7. 加一的golang实现

    给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一. 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字. 你可以假设除了整数 0 之外,这个整数不会以零开头. 输入: [,,] ...

  8. 获取当前页面的URL信息

    以前在做网站的时候,经常会遇到当前页的分类高亮显示,以便让用户了解当前处于哪个页面.之前一直是在每个不同页面写方法.工程量大,也不便于修改.一直在想有什么简便的方法实现.后来在网上查到可以用获取当前U ...

  9. 使用c#封装海康SDK出现无法加载 DLL“..\bin\HCNetSDK.dll”: 找不到指定的模块

    最近在研究网络摄像头的二次开发,测试了一款海康威视的网络摄像头,程序调试的时候,出现如题的报错. 调试随机自带的demo时,程序运行正常,但当把该程序引入到我自己的程序中时,就开始报错.根据开发软件包 ...

  10. 强化学习(三)—— 时序差分法(SARSA和Q-Learning)

    1.时序差分法基本概念 虽然蒙特卡洛方法可以在不知道状态转移概率矩阵的前提下,灵活地求解强化学习问题,但是蒙特卡洛方法需要所有的采样序列都是完整的状态序列.如果我们没有完整的状态序列就无法用蒙特卡洛方 ...