因为最近在学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 ;
}

最新文章

  1. jquery仿淘宝规格颜色选择效果
  2. 创建第一个JBPM6项目并且运行自带的helloword例子(JBPM6学习之三)
  3. Linux 新手非常有用的命令
  4. 使用mysql函数 group_concat 一点需要注意的
  5. 11.2.0.3.7 PSU补丁升级
  6. PHP - 验证用户名
  7. 高效 Java Web 开发框架 JessMA v3.2.3 beta-1 发布
  8. Xssf配合metaspolit使用
  9. ctags的使用
  10. python requests库学习笔记(下)
  11. Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap
  12. 怎样用css写出一个下拉菜单
  13. 惊奇!用Java也能实现比特币系统
  14. sweetalert提示框
  15. python 三大框架之一Django入门
  16. Java-常用工具方法
  17. Spring Developer Tools 源码分析:二、类路径监控
  18. gitlab 源码安装=》rpm安装横向迁移(version 9.0)
  19. Python--001
  20. 百万级数据 MySQL处理(转)

热门文章

  1. 【微信小游戏】【提审的坑】!#¥%&amp;……&amp;&amp;……%¥#@@*()()&amp;%%¥
  2. Java操作Excel(使用JXL)
  3. Linux 基本操作--文件查看 (day3)
  4. 【Linux基础】VM使用
  5. element ui Angular学习笔记(一)
  6. (转)Spring Boot(十一):Spring Boot 中 MongoDB 的使用
  7. nginx配置tomcat负载均衡,nginx.conf配置文件的配置
  8. 7.01-beautiful_soup2
  9. SQLite 知识摘要 --- 线程模式、事务模式
  10. Error: client: etcd cluster is unavailable or misconfigured; error #0: dial tcp 127.0.0.1:4001: getsockopt: connection refused