离心率计算

4.1.16 The eccentricity of a vertex v is the the length of the shortest path from that vertex to the furthest vertex from v. The diameter of a graph is the maximum eccentricity of any vertex. The radius of a graph is the smallest eccentricity of any vertex. A center is a vertex whose eccentricity is the radius. Implement the following API:
GraphProperties
4.1.18 The girth of a graph is the length of its shortest cycle. If a graph is acyclic, then its girth is infinite. Add a method girth() to GraphProperties that returns the girth of the graph. Hint : Run BFS from each vertex. The shortest cycle containing s is a shortest path from s to some vertex v, plus the edge from v back to s.

题目释义
4.1.16 计算点的离心率,图的直径,半径,中心
4.1.18 计算图的围长

定义
点的离心率:图中任意一点v,v的离心率是图中其他点到v的所有最短路径中最大值。
图的直径:图中所有点的离心率的最大值。
图的半径:图中所有点的离心率的最小值。
图的中心:图中离心率长度等于半径的点。
图的围长:如果图中有环,围长则为所有环的长度的最小值。

算法思路
广度优先路径

  • 因为要计算距离,需要一个数组int[] distTo记录距离。可以和数组 boolean[] marked 进行合并 。
    distTo[] 初始值设为-1,表示未被寻访。一旦被寻访到,就改为其到顶点的距离。

  • 改动

    • 离心率计算,在bfp遍历中增加distTo的赋值即可。

    • 环计算,寻访到一个已经被寻访过的顶点,即说明出现了环。

  • 异常抛出问题还不是很熟练,故未对图非连通的情况进行判别抛出异常


import java.util.*;

public class GraphProperties {
    //private懒得写了
    int[] distTo; //到顶点的距离
    int[] e; //离心率
    int[] c; //cycle
    int[] edgeTo; //前任(是谁牵着你的手走到这条路?)
    
    int diameter = 0;
    int radius = Integer.MAX_VALUE;
    int center;
    int girth = Integer.MAX_VALUE;
    
    //异常抛出问题还不是很熟练,先不考虑
    GraphProperties(Graph G) {
        int V = G.V();
        distTo = new int[V];
        e = new int[V];
        c = new int[V];
        edgeTo = new int[V];
        
        //遍历所有的顶点,造v棵树
        for (int v = 0; v < V; v++) { 
            bfp(G, v);
        }
        
        //找各个最大最小值,各找各妈,各赋各值
        for (int v = 0; v < V; v++) {
            diameter = e[v] > diameter ? e[v] : diameter;
            if (e[v] < radius) {
                radius = e[v];
                center = v;
            }
            girth = c[v] < girth ? c[v] : girth;
        }
    }
    
    //主算法
    void bfp(Graph G, int s) {
        int eccen = 0;
        int cycle = Integer.MAX_VALUE;
        
        for (int v = 0; v < G.V(); v++)
            distTo[v] = -1; //初始化为0,表示未被寻访过
        distTo[s] = 0;
        Queue<Integer> q = new LinkedList<Integer>();
        q.offer(s);
        while (!q.isEmpty()) {
            int v = q.poll();
            for (int w : G.adj(v)) {//v是我,w是我的前女友们
                if (distTo[w] == -1) { //如果未被寻访过
                    distTo[w] = distTo[v] + 1; //记录距离
                    eccen = distTo[w]; //这是深度优先算法,因此最后一个被寻访的深度就是最深的
                } else if ( w!= edgeTo[v] ) { //遇到一个寻访过的w,就说明牵着现在老婆的手遇到了前女朋友,人生兜兜转转形成了一个环(前提是你遇到的不是你老婆)
                    int d = distTo[w] + distTo[v] + 1; //算一下绕了多大的一个圈
                    cycle = d < cycle ? d : cycle; //记录最小的那个圈,走最小的套路
                }
            }
        }
        e[s] = eccen;
        c[s] = cycle;
    }

    // diameter of G 图的直径:图中所有点的离心率的最大值。
    public int diameter() {
        return diameter;
    }

    // radius of G 图的半径:图中所有点的离心率的最小值。
    public int radius() {
        return radius;
    }

    // center of G 图的中心:图中离心率的最小值所对的顶点。
    public int center() {
        return center;
    }

    // grith of G 图的围长:如果图中有环,围长则为所有环的长度的最小值。
    public int girth() {
        return girth;
    }

}

lindsay_bubble
26 声望11 粉丝