/********************************************** 2015.1.9---1.12 by yzk ************************************************************************/
<pre name="code" class="java">import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.lang.Thread;
import java.lang.Runnable;
public class init
{
public static void main(String[] args) throws Exception
{
//Graph g2=new Graph();
// login my=new login();
Graph g1=new Graph();
// Thread my=new Thread(g2);
// my.start();
//g1.gos();
// g2.start();
// g1.readin();
// g1.play();
//g1.setVisible(true);
}
}
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.lang.Thread;
import java.lang.Runnable;
public class Graph extends JFrame
{
public static int wait=0;
JButton stop= new JButton("STOP"); //暫停按鈕
JButton go= new JButton("GO"); //開始按鈕
public Graph ()throws Exception
{
setBounds(0, 0, 1380, 800); //設定大小
this.setBackground(Color.WHITE); //背景色
this.setTitle("基於OSPF協議的有向圖最短路Dijkstra算法動態過程演示系統");
this.setLayout(null);
JLabel lblNewLabel = new JLabel("<html>最<br>短<br>路<br>算<br>法<br>動<br>態<br>過<br>程");
lblNewLabel.setFont(new Font("長城行楷體", Font.BOLD, 60)); //標籤相關設置
lblNewLabel.setVerticalAlignment(SwingConstants.TOP); //置頂
lblNewLabel.setForeground(new Color(0, 0, 0));
lblNewLabel. setBounds(20,0,90,800);
add(lblNewLabel);
Gra temp=new Gra(); // 建圖
temp.setBounds(90, 0, 1290, 800);
temp.readin();
add(temp);
this.setVisible(true);
temp.play(); //演示算法過程
}
}
class Gra extends JPanel
{
int [] head; //鏈式前向星存圖
int [][] edge;
int nume;
int maxn; //頂點數
int maxm; //邊數
int inf=0x3f3f3f3f; //無窮大
int ss,tt; //源匯點
int change; //開關量
int []mark; //最短路的標記
int []dis; //距離
int []got; //是否需要閃爍標記(正在被更新)
points [] dian; //點類
int [][] lines;
public Gra() //初始化構造函數
{
head=new int [1005];
edge=new int [5000][3];
lines= new int [10000][5];
dis=new int [1006];
got=new int [5000];
mark=new int [1006];
nume=0;
change=0;
for(int i=0;i<1000;i++)
{
head[i]=-1;dis[i]=inf;got[i]=mark[i]=0;
}
}
public void adde(int i,int j,int w) //添加一條有向邊
{
edge[nume][0]=j;edge[nume][1]=head[i];head[i]=nume;
edge[nume++][2]=w;
}
void magic0() //延時重畫函數
{
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.repaint();
}
void magic() //閃爍控制函數
{
int cur=5; //變換次數
while(cur!=0)
{
change=1; //燈開
magic0();
change=0; //燈滅
magic0();
cur--;
//System.out.println(cur);
}
}
public void readin ()throws Exception //讀入圖函數
{
java.io.File file= new java.io.File("scores.txt"); //讀入數據
// java.io.File file= new java.io.File("scores2.txt"); //讀入數據
// java.io.File file= new java.io.File("radscores.txt");
Scanner input =new Scanner(file);
while(input.hasNext())
{
maxn=input.nextInt();
maxm=input.nextInt();
int from,to,w;
for(int i=0;i<maxm;i++)
{
from=input.nextInt();
to=input.nextInt();
w=input.nextInt();
adde(from,to,w);
}
ss=input.nextInt(); tt=input.nextInt();
dis[ss]=0;
}
input.close();
java.io.File file2 = new java.io.File("points.txt"); //讀入座標點
// java.io.File file2 = new java.io.File("points2.txt");
//java.io.File file2= new java.io.File("radpoints.txt");
Scanner input2 =new Scanner(file2);
dian =new points [maxn+1];
for(int i=1;i<=maxn;i++)
{
dian[i]=new points(input2.nextInt(),input2.nextInt());
}
}
public void play() //Dijkstra算法
{
int marks=1;
while(marks==1)
{
int mins=inf;
marks=0;
int cur=0;
for(int i=1;i<=maxn;i++)
{
if(mark[i]==0&&dis[i]<mins)
{
mins=dis[i];
cur=i;
marks=1;
}
}
got[cur]=1; //點需要閃
magic();
got[cur]=0; //關閉該點,之後就不再閃
mark[cur]=1;
for(int j=head[cur];j!=-1;j=edge[j][1])
{
int to=edge[j][0];
if(mark[to]==0&&dis[to]>dis[cur]+edge[j][2])
{
dis[to]=dis[cur]+edge[j][2];
lines[j][0]=1; //該線已變色
lines[j][1]=1; //該線需要閃
magic();
lines[j][1]=0; //無需再閃
}
}
}
}
protected void paintComponent( Graphics g) //畫圖函數
{
super.paintComponent(g); //清屏
g.setColor(Color.green);
Font font = new Font("Arial", Font.BOLD, 25); //字體大小
g.setFont(font);
for(int i=1;i<=maxn;i++)
{
if(got[i]==1) //該點在閃
{
if(change==1) //燈開
g.setColor(Color.red);
else g.setColor(Color.GREEN); //燈滅
}
else
{
if(mark[i]==1) //該點已變
g.setColor(Color.red);
else g.setColor(Color.GREEN);
}
g.fillOval(dian[i].x, dian[i].y, 50, 50);
String ts;
if(dis[i]==inf)
ts="+∞";
else ts=new String().valueOf(dis[i]);
g.drawString(ts,dian[i].x,dian[i].y);
}
g.setColor(Color.GRAY);
for(int i=1;i<=maxn;i++)
{
for(int j=head[i];j!=-1;j=edge[j][1])
{
if(lines[j][1]==1) //需要閃爍
{
if(change==1)
g.setColor(Color.BLUE);
else g.setColor(Color.GRAY);
}
else
{
if(lines[j][0]==1) //已經變色
g.setColor(Color.BLUE);
else g.setColor(Color.GRAY);
}
// g.drawString(new String().valueOf(dis[edge[j][2]]),dian[i].x,dian[i].y);
Graphics2D g2= (Graphics2D)g;
drawAL(dian[i].x+25,dian[i].y+25, dian[edge[j][0]].x+25, dian[edge[j][0]].y+25,g2); //劃邊
// g.drawLine(dian[i].x+25,dian[i].y+25, dian[edge[j][0]].x+25, dian[edge[j][0]].y+25);
int mx=(dian[i].x+25+dian[edge[j][0]].x+25)/2;
int my=(dian[i].y+25+dian[edge[j][0]].y+25)/2;
g.drawString(new String().valueOf(edge[j][2]), mx,my);
}
}
}
public static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2)
{
double H = 20; // 箭頭高度
double L = 6; // 底邊的一半
int x3,y3,x4,y4;
double awrad = Math.atan(L / H); // 箭頭角度
double arraow_len = Math.sqrt(L * L + H * H); // 箭頭的長度
double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端點
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端點
double y_4 = ey - arrXY_2[1];
Double X3 = new Double(x_3);
x3 = X3.intValue();
Double Y3 = new Double(y_3);
y3 = Y3.intValue();
Double X4 = new Double(x_4);
x4 = X4.intValue();
Double Y4 = new Double(y_4);
y4 = Y4.intValue();
g2.drawLine(sx, sy, ex, ey); // 畫線
GeneralPath triangle = new GeneralPath();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.closePath();
g2.fill(triangle); //實心箭頭
//g2.draw(triangle); //非實心箭頭
}
public static double[] rotateVec(int px, int py, double ang, // 計算箭頭的左右倆的點
boolean isChLen, double newLen)
{
double mathstr[] = new double[2];
// 參數含義分別是x分量、y分量、旋轉角、是否改變長度、新長度
double vx = px * Math.cos(ang) - py * Math.sin(ang);
double vy = px * Math.sin(ang) + py * Math.cos(ang);
if (isChLen) {
double d = Math.sqrt(vx * vx + vy * vy);
vx = vx / d * newLen;
vy = vy / d * newLen;
mathstr[0] = vx;
mathstr[1] = vy;
}
return mathstr;
}
}
class points
{
int x,y;
points(){};
points(int x,int y)
{
this.x=x;
this.y=y;
}
}