bangnaga icon

Dijkstra.java

bangnaga | PRO | 05/01/12 12:38:40 PM UTC | 0 ⭐ | 412 👁️ | Never ⏰ | []
Java |

9.8 KB

|

None

|

0 👍

/

0 👎

/********************************************/
/* Dijkstra.java                            */
/* Copyright (C) 1997, 1998, 2000  K. Ikeda */
/********************************************/
 
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.net.URL;
 
class Node {
    int x;
    int y;
    int delta_plus; /* edge starts from this node */
    int delta_minus;    /* edge terminates at this node */
    int dist;       /* distance from the start node */
    int prev;       /* previous node of the shortest path */
    int succ,pred;  /* node in Sbar with finite dist. */
    int w;
    int h;
    int pw;
    int dx;
    int dy;
    String  name;
}
 
class Edge {
    int rndd_plus;  /* initial vertex of this edge */
    int rndd_minus; /* terminal vertex of this edge */
    int delta_plus; /* edge starts from rndd_plus */
    int delta_minus;    /* edge terminates at rndd_minus */
    int len;        /* length */
    String  name;
}
 
public class Dijkstra extends Applet implements MouseListener {
    int n,m;
    int u,snode;    /* start node */
    int pre_s_first, pre_s_last;
    boolean isdigraph;
    int iteration, step;
    Node    v[] = new Node[100];
    Edge    e[] = new Edge[200];
 
    int findNode(String name) {
        for (int i=0; i<n; i++)
            if (v[i].name.equals(name))
                return i;
        return -1;
    }
 
    void input_graph(InputStream is) throws IOException {
        int x,y,l;
        String  s;
 
        Reader r = new BufferedReader(new InputStreamReader(is));
        StreamTokenizer st = new StreamTokenizer(r);
        st.commentChar('#');
        st.nextToken(); n = (int)st.nval;
        st.nextToken(); m = (int)st.nval;
        st.nextToken(); s = st.sval;
        isdigraph = "digraph".equals(s);
        for (int i = 0; i<n; i++) {
            Node node = new Node();
            st.nextToken(); node.name = st.sval;
            st.nextToken(); node.x = (int)st.nval;
            st.nextToken(); node.y = (int)st.nval;
            v[i] = node;
        }
        for (int i = 0; i<m; i++) {
            Edge edge = new Edge();
            st.nextToken(); edge.name = st.sval;
            switch (st.nextToken()) {
            case StreamTokenizer.TT_NUMBER:
                edge.rndd_plus = (int)st.nval;
                break;
            case StreamTokenizer.TT_WORD:
                edge.rndd_plus = findNode(st.sval);
                break;
            default:
                break;
            }
            switch (st.nextToken()) {
            case StreamTokenizer.TT_NUMBER:
                edge.rndd_minus = (int)st.nval;
                break;
            case StreamTokenizer.TT_WORD:
                edge.rndd_minus = findNode(st.sval);
                break;
            default:
                break;
            }
            st.nextToken(); edge.len = (int)st.nval;
            e[i] = edge;
        }
        for (int i=0; i<n; i++) {
            v[i].succ = v[i].pred = -2;
            v[i].prev = v[i].dist = -1;
            v[i].pw = 0;
        }
        iteration = step = 0;
    }
 
    void rdb() {
        int i,k;
 
        for (i=0; i<n; i++)
            v[i].delta_plus = v[i].delta_minus = -1;
        for (i=0; i<m; i++)
            e[i].delta_plus = e[i].delta_minus = -1;
        for (i=0; i<m; i++) {
            k = e[i].rndd_plus;
            if (v[k].delta_plus == -1)
                v[k].delta_plus = i;
            else {
                k = v[k].delta_plus;
                while(e[k].delta_plus >= 0)
                    k = e[k].delta_plus;
                e[k].delta_plus = i;
            }
            k = e[i].rndd_minus;
            if (v[k].delta_minus == -1)
                v[k].delta_minus = i;
            else {
                k = v[k].delta_minus;
                while(e[k].delta_minus >= 0)
                    k = e[k].delta_minus;
                e[k].delta_minus = i;
            }
        }
    }
 
    void append_pre_s(int i) {
        v[i].succ = v[i].pred = -1;
        if (pre_s_first<0)
            pre_s_first = i;
        else
            v[pre_s_last].succ = i;
        v[i].pred = pre_s_last;
        pre_s_last = i;
    }
 
    void remove_pre_s(int i) {
        int succ = v[i].succ;
        int pred = v[i].pred;
 
        if (succ>=0)
            v[succ].pred = pred;
        else
            pre_s_last = pred;
        if (pred>=0)
            v[pred].succ = succ;
        else
            pre_s_first = succ;
    }
 
    void step1() {      /* initialize */
        u = snode;
        for (int i=0; i<n; i++) {
            v[i].succ = v[i].pred = -2;
            v[i].prev = v[i].dist = -1;
        }
        v[u].succ = -3;
        v[u].dist = 0;
        pre_s_first = pre_s_last = -1;
    }
 
    void step2() {      /* replace labels */
        int i,j;
 
        j = v[u].delta_plus;
        while (j>=0) {
            i = e[j].rndd_minus;
            if ((v[i].succ>=-2)&&((v[i].dist<0)||
                (v[i].dist>v[u].dist+e[j].len))) {
                if (v[i].dist<0)
                    append_pre_s(i);
                v[i].dist = v[u].dist + e[j].len;
                v[i].prev = u;    /* label */
            }
            j = e[j].delta_plus;
        }
        if (!isdigraph) {
        j = v[u].delta_minus;
        while (j>=0) {
            i = e[j].rndd_plus;
            if ((v[i].succ>=-2)&&((v[i].dist<0)||
                (v[i].dist>v[u].dist+e[j].len))) {
                if (v[i].dist<0)
                    append_pre_s(i);
                v[i].dist = v[u].dist + e[j].len;
                v[i].prev = u;    /* label */
            }
            j = e[j].delta_minus;
        }
        }
        v[u].succ = -4;
    }
 
    void step3() {      /* find the shortest node in Sbar */
        int i,rho;
 
        rho = -1;
        for (i = pre_s_first; i>=0; i = v[i].succ) {
            if ((rho < 0)||(rho>v[i].dist)) {
                rho = v[i].dist;
                u = i;
            }
        }
        remove_pre_s(u);
        v[u].succ = -3;
    }
 
    void step4() {
        v[u].succ = -4;
    }
 
    double weight(Node n, double x, double y) {
        double  w,z,xx,yy;
 
        w = 0;
        for (int j = n.delta_plus; j>=0; j=e[j].delta_plus) {
            xx = (double)(v[e[j].rndd_minus].x - n.x);
            yy = (double)(v[e[j].rndd_minus].y - n.y);
            z = (x*xx+y*yy)/Math.sqrt((x*x+y*y)*(xx*xx+yy*yy))+1.0;
            w += z*z*z*z;
        }
        for (int j = n.delta_minus; j>=0; j=e[j].delta_minus) {
            xx = (double)(v[e[j].rndd_plus].x - n.x);
            yy = (double)(v[e[j].rndd_plus].y - n.y);
            z = (x*xx+y*yy)/Math.sqrt((x*x+y*y)*(xx*xx+yy*yy))+1.0;
            w += z*z*z*z;
        }
        return w;
    }
 
    void init_sub() {
        int x[] = {1, 0, -1, 1, 0, -1};
        int y[] = {1, 1, 1, -1, -1, -1};
        int     i,j,k;
        double  w,z;
 
        for (i=0; i<n; i++) {
            k=0;
            w=weight(v[i],(double)x[0],(double)y[0]);
            for (j=1; j<6; j++) {
                z=weight(v[i],(double)x[j],(double)y[j]);
                if (z<w) {
                    w = z;
                    k = j;
                }
            }
            v[i].dx = x[k];
            v[i].dy = y[k];
        }
    }
 
    public void init() {
        String mdname = getParameter("inputfile");
        try {
            InputStream is;
 
            is = new URL(getDocumentBase(),mdname).openStream();
            input_graph(is);
            try {
                if (is != null)
                    is.close();
                } catch(Exception e) {
            }
        } catch (FileNotFoundException e) {
            System.err.println("File not found.");
        } catch (IOException e) {
            System.err.println("Cannot access file.");
        }
 
        String s = getParameter("start");
        if (s != null)
            snode = Integer.parseInt(s);
        else
            snode = 0;
 
        setBackground(Color.white);
        rdb();
        init_sub();
        addMouseListener(this);
    }
 
    public void paintNode(Graphics g, Node n, FontMetrics fm) {
        String s;
        int x = n.x;
        int y = n.y;
        int w = fm.stringWidth(n.name) + 10;
        int h = fm.getHeight() + 4;
        n.w = w;
        n.h = h;
 
        if (n.succ<-2)
            g.setColor(Color.blue);
        else if (n.succ==-2)
            g.setColor(Color.gray);
        else
            g.setColor(Color.red);
 
        g.drawRect(x-w/2,y-h/2,w,h);
 
        if (n.succ==-4)
            g.setColor(Color.cyan);
        else if (n.succ==-3)
            g.setColor(Color.pink);
        else if (n.succ>-2)
            g.setColor(Color.yellow);
        else
            g.setColor(getBackground());
 
        g.fillRect(x-w/2+1,y-h/2+1,w-1,h-1);
 
        g.setColor(Color.black);
        g.drawString(n.name,x-(w-10)/2,(y-(h-4)/2)+fm.getAscent());
 
 
        if (n.dist<0)
            s = "";
        else
            s = ""+n.dist;
        w = fm.stringWidth(s) + 10;
        x += (h+1)*n.dx; y += (h+1)*n.dy;
        g.setColor(getBackground());
        g.fillRect(x-n.pw/2,y-h/2,n.pw,h);
        n.pw = w;
        if (n.succ<-2)
            g.setColor(Color.blue);
        else
            g.setColor(Color.red);
        g.drawString(s,x-(w-10)/2,y-(h-4)/2+fm.getAscent());
    }
 
    int [] xy(int a, int b, int w, int h) {
        int x[] = new int[2];
 
        if (Math.abs(w*b)>=Math.abs(h*a)) {
            x[0] = ((b>=0)?1:-1)*a*h/b/2;
            x[1] = ((b>=0)?1:-1)*h/2;
        } else {
            x[0] = ((a>=0)?1:-1)*w/2;
            x[1] = ((a>=0)?1:-1)*b*w/a/2;
        }
        return x;
    }
 
    void drawArrow(Graphics g,int x1,int y1,int x2,int y2) {
        int a = x1-x2;
        int b = y1-y2;
 
        if (isdigraph) {
        double  aa = Math.sqrt(a*a+b*b)/16.0;
        double  bb = b/aa;
            aa = a/aa;
        g.drawLine(x2,y2,x2+(int)((aa*12+bb*5)/13),y2+(int)((-aa*5+bb*12)/13));
        g.drawLine(x2,y2,x2+(int)((aa*12-bb*5)/13),y2+(int)((aa*5+bb*12)/13));
        }
        g.drawLine(x1,y1,x2,y2);
    }
 
    public void paintEdge(Graphics g, Edge e, FontMetrics fm) {
        Node v1 = v[e.rndd_plus];
        Node v2 = v[e.rndd_minus];
 
        int a = v1.x-v2.x;
        int b = v1.y-v2.y;
 
        int x1[] = xy(-a,-b,v1.w,v1.h);
        int x2[] = xy(a,b,v2.w,v2.h);
 
        if (v2.prev == e.rndd_plus) {
            if ((v1.succ<-2)&&(v2.succ>=-2))
                g.setColor(Color.red);
            else
                g.setColor(Color.blue);
        } else {
            g.setColor(Color.lightGray);
        }
        if ((!isdigraph)&&(v1.prev == e.rndd_minus)) {
            if ((v2.succ<-2)&&(v1.succ>=-2))
                g.setColor(Color.red);
            else
                g.setColor(Color.blue);
        }
        drawArrow(g,v1.x+x1[0],v1.y+x1[1],v2.x+x2[0],v2.y+x2[1]);
 
        int w = fm.stringWidth("" + e.len);
        int h = fm.getHeight();
 
        g.setColor(getBackground());
        g.fillRect((v1.x+v2.x-w)/2,(v1.y+v2.y-h)/2,w,h);
 
        if ((v2.prev == e.rndd_plus)||
            ((!isdigraph)&&(v1.prev == e.rndd_minus)))
            g.setColor(Color.black);
        else
            g.setColor(Color.lightGray);
        g.drawString("" + e.len,(v1.x+v2.x-w)/2,(v1.y+v2.y-h)/2+fm.getAscent());
    }
 
    public void paint(Graphics g) {
        FontMetrics fm = g.getFontMetrics();
        for (int i=0; i<n; i++)
            paintNode(g,v[i],fm);
        for (int i=0; i<m; i++)
            paintEdge(g,e[i],fm);
    }
 
    public void update(Graphics g) {
        paint(g);
    }
 
    public void mousePressed(MouseEvent ev) {
        if (iteration==0) {
            step1();
            iteration++;
            step = 2;
        } else if (iteration>=n) {
            step4();
            iteration = 0;
        } else {
            if (step == 2) {
                step2();
                step = 3;
            } else {
                step3();
                iteration++;
                step = 2;
            }
        }
        repaint();
    }
    public void mouseClicked(MouseEvent event) {}
    public void mouseReleased(MouseEvent event) {}
    public void mouseEntered(MouseEvent event) {}
    public void mouseExited(MouseEvent event) {}
}

Comments