本题分两步:

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算法题解的更多相关文章

  1. POJ 2553 The Bottom of a Graph (Tarjan)

    The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 11981   Accepted: ...

  2. POJ 2553 The Bottom of a Graph Tarjan找环缩点(题解解释输入)

    Description We will use the following (standard) definitions from graph theory. Let V be a nonempty ...

  3. [poj 2553]The Bottom of a Graph[Tarjan强连通分量]

    题意: 求出度为0的强连通分量. 思路: 缩点 具体有两种实现: 1.遍历所有边, 边的两端点不在同一强连通分量的话, 将出发点所在强连通分量出度+1. #include <cstdio> ...

  4. POJ 2553 The Bottom of a Graph(强连通分量)

    POJ 2553 The Bottom of a Graph 题目链接 题意:给定一个有向图,求出度为0的强连通分量 思路:缩点搞就可以 代码: #include <cstdio> #in ...

  5. poj 2553 The Bottom of a Graph(强连通分量+缩点)

    题目地址:http://poj.org/problem?id=2553 The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K ...

  6. poj 2553 The Bottom of a Graph【强连通分量求汇点个数】

    The Bottom of a Graph Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 9641   Accepted:  ...

  7. POJ 2553 The Bottom of a Graph (强连通分量)

    题目地址:POJ 2553 题目意思不好理解.题意是:G图中从v可达的全部点w,也都能够达到v,这种v称为sink.然后升序输出全部的sink. 对于一个强连通分量来说,全部的点都符合这一条件,可是假 ...

  8. poj 2553 The Bottom of a Graph : tarjan O(n) 存环中的点

    /** problem: http://poj.org/problem?id=2553 将所有出度为0环中的点排序输出即可. **/ #include<stdio.h> #include& ...

  9. POJ 2553 The Bottom of a Graph 【scc tarjan】

    图论之强连通复习开始- - 题目大意:给你一个有向图,要你求出这样的点集:从这个点出发能到达的点,一定能回到这个点 思路:强连通分量里的显然都可以互相到达 那就一起考虑,缩点后如果一个点有出边,一定不 ...

随机推荐

  1. poj 1811 Prim test

    基本上一个裸的Miller_Rabin大素数判定和一个裸的Pollard_rho素数分解算法,当模板用吧! #include<cstdio> #include<algorithm&g ...

  2. MySQL查询表结构的SQL小结

    mysql查看表结构命令,如下: desc 表名; show columns from 表名; describe 表名; show create table 表名; 示例: use testDB; # ...

  3. 135. Candy

    题目: There are N children standing in a line. Each child is assigned a rating value. You are giving c ...

  4. 132. Palindrome Partitioning II

    题目: Given a string s, partition s such that every substring of the partition is a palindrome. Return ...

  5. C# Json处理日期和Table

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Ru ...

  6. C++中为什么要用虚函数、指针或引用才能实现多态?

    原文链接:http://blog.csdn.net/zoopang/article/details/14071779 学过C++的都知道,要实现C++的多态性必须要用到虚函数,并且还要使用引用或者指针 ...

  7. spring junit class path resource [ /com/config/spring-core.xml] cannot be opened because it does not exist

    正确写法应该如下: @RunWith(SpringJUnit4ClassRunner.class) //@ContextConfiguration(locations="classpath: ...

  8. 【POJ】1054 The Troublesome Frog

    题目是非常经典的搜索+剪枝.题意简言之就是,青蛙需要沿着直线踩着踏点通过田地,并且踏点需要至少为3.问哪条路径青蛙踩坏的作物最多.很好的一个条件是青蛙每次移动都是等间距的.题目需要注意将其排序. #i ...

  9. Form Personalization应用总结

    1 Form Personalization 简介 Oracle EBS 11.5.10增加了Form Personalization功能,该功能不仅是技术功能的一次增强,也是对业务功能的扩展,提高了 ...

  10. 细说SQL性能优化

    1:在进行多表关联时,多用where语句把单个表的结果集最小化,多用聚合函数汇总结果集后再与其它表做关联,以使结果集数据量最小化2:在两张表进行关联时,应考虑可否使用右连接.以提高查询速度3:使用wh ...