图论,求有向图的强连通分支
来源:互联网 发布:疯狂java讲义好不好 编辑:程序博客网 时间:2024/04/26 20:25
求有向图的强联通分支十一个典型的图论题目。
本来想把他写成一个通用的算法,但是发现有很多不太好处理的地方,比如选用邻接链表还是选用邻接矩阵来表示图,有的情况是不一样的,再者很难把强联通分支缩点,并且再构建一个图出来,主要是强联通分支之间的边表示的时候要考虑一些情况,比如边的费用什么的。
但是也可以尝试做一个稍微通用的一点的算法,就是把所有点属于那个强连通标识(用id[i]表示)出来。
如果对于原图中两点i,j。 如果id[i]==id[j],则他们在一个强联通分支中,否则他们一定不在一个强联通分支中。至于确定两个不同强连通分支之间的关系,就留给客户去做,就好了。
先给出pku的一个题目,使用了求强联通分支的技术。
The Bottom of a Graph
Description
We will use the following (standard) definitions from graph theory. Let V be a nonempty and finite set, its elements being called vertices (or nodes). Let E be a subset of the Cartesian product V×V, its elements being called edges. Then G=(V,E) is called a directed graph.
Let n be a positive integer, and let p=(e1,...,en) be a sequence of length n of edges ei∈E such that ei=(vi,vi+1) for a sequence of vertices (v1,...,vn+1). Then p is called a path from vertex v1 to vertex vn+1 in G and we say that vn+1 is reachable from v1, writing (v1→vn+1).
Here are some new definitions. A node v in a graph G=(V,E) is called a sink, if for every node w in G that is reachable from v, v is also reachable from w. The bottom of a graph is the subset of all nodes that are sinks, i.e., bottom(G)={v∈V|∀w∈V:(v→w)⇒(w→v)}. You have to calculate the bottom of certain graphs.
Input
The input contains several test cases, each of which corresponds to a directed graph G. Each test case starts with an integer number v, denoting the number of vertices of G=(V,E), where the vertices will be identified by the integer numbers in the set V={1,...,v}. You may assume that 1<=v<=5000. That is followed by a non-negative integer e and, thereafter, e pairs of vertex identifiers v1,w1,...,ve,we with the meaning that (vi,wi)∈E. There are no edges other than specified by these pairs. The last test case is followed by a zero.
Output
For each test case output the bottom of the specified graph on a single line. To this end, print the numbers of all nodes that are sinks in sorted order separated by a single space character. If the bottom is empty, print an empty line.
Sample Input Sample Output3 3
1 3 2 3 3 1
2 1
1 2
01 3
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class Main
{
static LinkedList [] mapa;
static LinkedList [] mapt;
static int [] order;
static int tag;
static boolean [] vst;
static int [] id;
static int [] id_degree_cnt;
public static void main(String[] args) throws IOException
{
BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(System.out);
while(true)
{
int n=0,m=0;
try
{
String s=cin.readLine().trim();
String [] sa=s.split(" +");
n=Integer.parseInt(sa[0]);
if(n==0)break;
m=Integer.parseInt(sa[1]);
mapa=new LinkedList[n];
mapt=new LinkedList[n];
for(int i=0;i<n;i++)
{
mapa[i]=new LinkedList<Integer>();
mapt[i]=new LinkedList<Integer>();
}
if(m>=0)
{
s=cin.readLine().trim();
sa=s.split(" +");
}
else sa=new String[] {};
for(int i=0;i<sa.length;i+=2)
{
int from=Integer.parseInt(sa[i])-1;
int to=Integer.parseInt(sa[i+1])-1;
mapa[from].add(to);
mapt[to].add(from);
}
}catch(Exception e)
{
}
order=new int[n];
tag=0;
vst=new boolean[n];
for(int i=0;i<n;i++)
if(vst[i]==false)
{
vst[i]=true;
dfsa(i);
}
id=new int[n];
tag=0;
Arrays.fill(vst,false);
for(int i=n-1;i>=0;i--)
{
if(vst[order[i]]==false)
{
vst[order[i]]=true;
dfst(order[i]);
tag++;
}
}
id_degree_cnt=new int[tag];
for(int i=0;i<n;i++)
{
LinkedList ll=mapa[i];
for(int j=0;j<ll.size();j++)
{
int next=(Integer)ll.get(j);
if(id[i]!=id[next])
id_degree_cnt[id[i]]++;
}
}
List<Integer>rel=new ArrayList<Integer>(n);
for(int i=0;i<n;i++)
if(id_degree_cnt[id[i]]==0)
rel.add(i);
for(int d:rel)
out.print((d+1)+" ");
out.println();
}
out.flush();
out.close();
}
public static void dfsa(int ci)
{
for(int i=0;i<mapa[ci].size();i++)
{
int next=(Integer)mapa[ci].get(i);
if(vst[next]==false)
{
vst[next]=true;
dfsa(next);
}
}
order[tag++]=ci;
}
public static void dfst(int ci)
{
id[ci]=tag;
for(int i=0;i<mapt[ci].size();i++)
{
int next=(Integer)mapt[ci].get(i);
if(vst[next]==false)
{
vst[next]=true;
dfst(next);
}
}
}
}
2
- 图论,求有向图的强连通分支
- 有向图的强连通分支
- 有向图的强连通分支
- 算法设计与分析:第六章 图 6.2求有向图的强连通分支
- 求有向图的强连通分支(邻接表存储)C++实现
- 算法基础 - 求有向图的强连通分支(Tarjan算法)
- 求有向图的强连通分支(邻接表存储)C++实现
- 有向图强连通分支
- 寻找有向图的强连通分支
- 有向图的强连通分支及DAG
- Kosaraju算法查找有向图的强连通分支
- 有向图强连通分支的Tarjan算法
- 如何编程求有向图的单向连通分支
- Tarjan求有向图的强连通分量
- Kosaraju_Algorithm求有向图的强连通分量
- ccf+tarjan+求有向图的强连通分量
- 求有向图的强连通分量<Tarjan>
- Java求出矩阵表示的有向图所有的强连通分支程序设计过程
- Wince下透明Label的实现(vb.net)
- OpenGL教程之纹理映射
- OpenGL教程之纹理映射
- 基本的Hibernate配置文件
- 学习安装Debian
- 图论,求有向图的强连通分支
- Core Dump
- bind 查询日志与一般启动日志分离保存
- MySQL直接执行和预处理执行效率比较示例
- 4. 焦点
- 【小阅读^大脑袋】0129 NO.308
- 一道有趣的数字算法题
- java中的死锁和数据库死锁
- Oracle BPEL vs jBPM