POJ 2553 The Bottom of a Graph TarJan算法题解
本题分两步:
1 使用Tarjan算法求全部最大子强连通图。而且标志出来
2 然后遍历这些节点看是否有出射的边,没有的顶点所在的子强连通图的全部点,都是解集。
Tarjan算法就是模板算法了。
这里使用一个数组和一个标识号,就能够记录这个顶点是属于哪个子强连通图的了。
然后使用DFS递归搜索全部点及其边,假设有边的还有一个顶点不属于本子强连通图。那么就说明有出射的边。
有难度的题目:
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <stack>
using namespace std; const int MAX_VEC = 5005;
int n, m;
vector<int> gra[MAX_VEC];
stack<int> stk;
int dfn[MAX_VEC];//tarjan算法记录深度探索得到的标号
int low[MAX_VEC];//tarjan算法记录回溯得到的最低顶点编号
bool inStk[MAX_VEC];//记录是否在栈里面,也能够记录是否被訪问过了
int connectGrp[MAX_VEC];//标志所属的连通子图标号 == connectNum
int vecNum;//顶点标号
int connectNum;//最大强连通子图标号
int out[MAX_VEC];//出度记录 void tarjan(int u)
{
dfn[u] = low[u] = vecNum++;
stk.push(u);
inStk[u] = 1;
for (int i = 0; i < (int)gra[u].size(); i++)
{
int v = gra[u][i];
if (!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);//两处的不同,和含义不同
}
else if (inStk[v]) low[u] = min(dfn[v], low[u]);//两处的不同
}
if (low[u] == dfn[u])
{
++connectNum;
while (stk.size())
{
int v = stk.top(); stk.pop();
inStk[v] = false;
connectGrp[v] = connectNum;
if (u == v) return;
}
}
} void solveConnect()
{
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(inStk, 0, sizeof(inStk));
for (int i = 1; i <= n; i++)
{
if (!dfn[i]) tarjan(i);
}
} void dfsCountOut(int u)
{
inStk[u] = true; //记录是否被訪问过了
for (int i = 0; i < int(gra[u].size()); i++)
{
int v = gra[u][i];
if (connectGrp[u] != connectGrp[v])
{
out[connectGrp[u]]++;//这个组的出度添加; connectGrp[] == connectNum
}
if (!inStk[v]) dfsCountOut(v);//深度优先,不须要使用额外空间
}
} void countConnectOut()
{
memset(inStk, 0, sizeof(inStk)); //这里仅仅记录是否被訪问过的了。
memset(out, 0, sizeof(out));
for (int i = 1; i <= n; i++)
{
if (!inStk[i]) dfsCountOut(i);
}
} int main()
{
int u, v;
while (scanf("%d", &n) && n)
{
connectNum = 0;
vecNum = 1;
scanf("%d", &m);
for (int i = 1; i <= n; i++)
gra[i].clear();
while (stk.size()) stk.pop(); //清零。重中之重 for (int i = 0; i < m; i++)
{
scanf("%d %d", &u, &v);
gra[u].push_back(v); //有向图
} solveConnect();
countConnectOut(); for(int i = 1; i <= n; ++i)
if(out[connectGrp[i]] == 0)
printf("%d ", i);
putchar('\n');
}
return 0;
}
POJ 2553 The Bottom of a Graph TarJan算法题解的更多相关文章
- POJ 2553 The Bottom of a Graph (Tarjan)
The Bottom of a Graph Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 11981 Accepted: ...
- POJ 2553 The Bottom of a Graph Tarjan找环缩点(题解解释输入)
Description We will use the following (standard) definitions from graph theory. Let V be a nonempty ...
- [poj 2553]The Bottom of a Graph[Tarjan强连通分量]
题意: 求出度为0的强连通分量. 思路: 缩点 具体有两种实现: 1.遍历所有边, 边的两端点不在同一强连通分量的话, 将出发点所在强连通分量出度+1. #include <cstdio> ...
- POJ 2553 The Bottom of a Graph(强连通分量)
POJ 2553 The Bottom of a Graph 题目链接 题意:给定一个有向图,求出度为0的强连通分量 思路:缩点搞就可以 代码: #include <cstdio> #in ...
- poj 2553 The Bottom of a Graph(强连通分量+缩点)
题目地址:http://poj.org/problem?id=2553 The Bottom of a Graph Time Limit: 3000MS Memory Limit: 65536K ...
- poj 2553 The Bottom of a Graph【强连通分量求汇点个数】
The Bottom of a Graph Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 9641 Accepted: ...
- POJ 2553 The Bottom of a Graph (强连通分量)
题目地址:POJ 2553 题目意思不好理解.题意是:G图中从v可达的全部点w,也都能够达到v,这种v称为sink.然后升序输出全部的sink. 对于一个强连通分量来说,全部的点都符合这一条件,可是假 ...
- poj 2553 The Bottom of a Graph : tarjan O(n) 存环中的点
/** problem: http://poj.org/problem?id=2553 将所有出度为0环中的点排序输出即可. **/ #include<stdio.h> #include& ...
- POJ 2553 The Bottom of a Graph 【scc tarjan】
图论之强连通复习开始- - 题目大意:给你一个有向图,要你求出这样的点集:从这个点出发能到达的点,一定能回到这个点 思路:强连通分量里的显然都可以互相到达 那就一起考虑,缩点后如果一个点有出边,一定不 ...
随机推荐
- 想使用 MongoDB ,你应该了解这8个方面!
应用性能高低依赖于数据库性能,MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写,旨在为 WEB 应用提供可扩展的高性能数据存储解决方案.MongoDB 是一个介于关系数据库和非关 ...
- php PDO连接mysql以及字符乱码处理
<?php //mysql 的 PDO $dsn = "mysql:dbname=cqkx;host:localhost"; $username = "root&q ...
- 网络基本功(八):细说TCP滑动窗口
https://community.emc.com/message/842129#842129
- PHP remove,empty和detach区别
empty: 把所有段落的子元素(包括文本节点)删除 HTML 代码: <p>Hello, <span>Person</span> <a href=" ...
- 【原创】MIPS浅议之——中断系统之我见
最近,准确的说应该是最近两个月的时间,我都在研究MIPS的异常与中断.或者可以说,最近这两个月,我才真正了解中断系统的整个结构和处理流程以及为什么要这样做?这段时间我最大的体会就是以前我们在“计算机组 ...
- MySQL海量数据查询优化策略
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- 【转】G++ 处理 /usr/bin/ld: cannot find -lc
原文网址:http://blog.sina.com.cn/s/blog_67bbb71101010tto.html 用g++编译C++程序时显示出:/usr/lib/ld: cannot find - ...
- How to Set Word Document Properties with C#
Word properties shows a brief description about one document. Through properties, we can learn gener ...
- android 利用数字证书对程序签名
签名的必要性 1. 防止你已安装的应用被恶意的第三方覆盖或替换掉. 2. 开发者的身份标识,签名可以防止抵赖等事件的发生. 开发Android的人这么多,完全有可能大家都把类名,包名起成了一个同样 ...
- .net软件自动化测试笔记(API-2)
1.9获得测试运行时间如何获得测试运行的总时间设计:DateTime.Now属性记录测试开始运行时间,以及测试结束时间,用一个TimeSpan对象计算本次运行的总时间 DateTime starTim ...