图--有向图

有向图由一组顶点和一组有方向的边组成

有向图的API

public classDigraph-
Digraph(int v)
Digraph(In in)
intV()顶点数
intE()边数
voidaddEdge(int v, int w)添加边v-w
Iterableadj(int v)和v相邻的所有顶点
Digraphreverse该图的反向图
StringtoString()

有向环

寻找有向环

public class DirectedCycle {
    private boolean marked[];
    private int[] edgeTo;
    private Stack<Integer> cycle; //有向环中的所有顶点(如果存在)
    private boolean[] onStack;    //递归调用的栈上的所有顶点

    public DirectedCycle(Digraph g){
        onStack = new boolean[g.V()];
        edgeTo = new int[g.V()];
        marked = new boolean[g.V()];
        for(int v=0; v<g.V(); v++)
            if(!marked[v]) dfs(g, v);
    }

    public void dfs(Digraph g, int v){
        onStack[v] = true; //调用v时设为true,调用结束设为false
        marked[v] = true;
        for(int w : g.adj(v)){
            if(this.hasCycle()) return;
            else if(!marked[w]){
                edgeTo[w] = v;
                dfs(g, w);
            }else if(onStack[w]){
                cycle = new Stack<Integer>();
                for(int x=v; x!=w; x=edgeTo[x])
                    cycle.push(x); //4 3 3为栈底
                cycle.push(w);   // 5 4 3
                cycle.push(v);  // 3 5 4 3
            } 
            onStack[v] = false;
        }
    }

    public boolean hasCycle(){
        return cycle!=null;
    }

    public Iterable<Integer> cycle(){
        return cycle;
    }
}

顶点排序(有向无环图)


  • 前序: 在递归调用之前将顶点加入队列
  • 后序: 在递归调用之后将顶点加入队列
  • 逆后序: 在递归调用之后将顶点压入栈

拓扑排序:之前(指向此任务的任务)任务已完成
一幅有向无环图的拓扑顺序即为所有顶点的逆后序排列

DepthFirstOrder(Graph g)-
pre前序
post后序
reversePost逆后序

强连通性

如果一幅有向图中的任意两个顶点都是强连通的(互相可达),则称这幅有向图是强连通的.

计算强连通分量的Kosaraju算法

  • 使用深度优先搜索查找给定有向图G1的反向图G2,
  • 得到G2所有顶点的逆后序
  • 使用深度优先搜索处理有向图G1(按照第二步所得顺序)
public class KosarajuSCC {
    private boolean[] marked;
    private int[] id;
    private int count;

    public KosarajuSCC(Digraph g){
        marked = new boolean[g.V()];
        id = new int[g.V()];
        DepthFirstOrder order = new DepthFirstOrder(g.reverse()); //反向图
        for(int s : order.reversePost()){                         //反向图的逆后序遍历
            if(!marked[s]){
                dfs(g, s);
                count++;
            }
        }
    }

    private void dfs(Digraph g, int v){
        marked[v] = true;
        id[v] = count;
        for(int w : g.adj(v))
            if(!marked[w]) dfs(g, w);   //递归
    }

    public boolean stronglyConnected(int v, int w){
        return id[v]==id[w];
    }

    public int id(int v){
        return id[v];
    }

    public int count(){
        return count;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值