问题描述:
题目描述:
已知一个无向图G=(V,E),G 中任意两个顶点 u 、v 之间存在路径或者不存在路径,如果存在,则会有一个或者多个最短路径。给出两个顶点 u0 和v0,请用一种效率尽可能高的算法求u0和v0之间的所有的最短路径。
输入:
第1 行:图的顶点数 1<=N<10 和边数 1<=M<=N*(N-1)/2 ,第 2...M+1行:图中的边(u,v ,w),其中 u 为边起点,v 为边终点,w 为边的权值(u 、v 、w 均为整数,1<=u<=N ,1<=v<=N ,1<=w<=100 ),第 M+2 行:u0和v0。
输出:
如果u0 和v0 之间没有路径,输出 0 ;其它情况:第 1 行为最短路径的条数 S 和最短路径的长度D,第 2...S+1 行中的每一行为最短路径的顶点序列 T_i(1<=i<=S) ,其中,T_1 、T_2、... 、T_S 的顺序要满足 T_i 的反向序列的字典序小于T_i+1 的反向序列的字典序的条件。例如,样例中T_1=<2,4>的反向序列为<4,2>,T_2=<2,3 ,4>的反向序列为<4,3 ,2>,则有<4,2>的字典序小于<4,3 ,2>的字典序。
输入示例:
输入示例:
5 8
2 1 2
1 5 2
2 3 5
2 4 6
2 5 5
3 4 1
3 5 1
4 5 2
2 4
输出示例:
4 6
2 4
2 3 4
2 1 5 3 4
2 1 5 4
下面是代码实现,方法为Dijestra标号发,复杂度为O(n^3),代码随便写写,还没整理:
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;
public class MainTry2 {
/**
* @param args
*/
public static void main(String[] args) {
Net net;
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter(System.getProperty("line.separator"));
String temps = scanner.next();
String[] headline = temps.split(" ");
int nodesCount = Integer.parseInt(headline[0]);
int edgeCount = Integer.parseInt(headline[1]);
net = new Net(nodesCount, edgeCount);
try {
for (int i = 0; i < edgeCount; i++) {
parseline(net, scanner.next());
}
String[] tailLine = scanner.next().split(" ");
int beginNode = Integer.parseInt(tailLine[0]);
int endNode = Integer.parseInt(tailLine[1]);
net.beginNodeid = beginNode;
net.endNodeid = endNode;
// System.out.println("\r\n ndoescoutn:" + net.nodesCount
// + " edgeCoutn" + net.edgeCount + " beinNode"
// + net.beginNodeid + " endNode" + net.endNodeid);
} catch (Exception e) {
System.out.println(e.getMessage());
}
net.DijestraTagging();
// System.out.println("hello over");
}
private static void parseline(Net net, String line) {
Scanner linescanner = new Scanner(line);
linescanner.useDelimiter(" ");
int t1 = linescanner.nextInt();
int t2 = linescanner.nextInt();
int t3 = linescanner.nextInt();
// System.out.println(t1 + " " + t2+" "+t3);
net.initEdge(t1, t2, t3);
}
}
class Net {
int MAXPOACH;
int nodesCount;
int edgeCount;
int[][] netEdges;
int[][] flagAndEdge;
int beginNodeid;
int endNodeid;
Node[] nodes;
HashSet<Node> netNodeSet = new HashSet<Node>();
String[] reversePaths;
static int currentnthPath;
Net(int nodeCount, int edgeCount) {
// MAXPOACH=nodeCount^nodeCount;
this.nodesCount = nodeCount;
this.edgeCount = edgeCount;
netEdges = new int[nodeCount + 1][nodeCount + 1];
flagAndEdge = new int[4][nodeCount + 1]; // [2] 前节点 [3] 是否有多个前节点
nodes = new Node[nodeCount + 1];
for (int i = 1; i < nodeCount + 1; i++) {
nodes[i] = new Node(i);
}
reversePaths = new String[nodesCount * nodesCount];
}
public void initEdge(int edgeNodeid1, int edgeNodeid2, int edgeWeight) {
netEdges[edgeNodeid1][edgeNodeid2] = edgeWeight;
netEdges[edgeNodeid2][edgeNodeid1] = edgeWeight;
}
public void printNetEdgeForDebugging() {
for (int i = 0; i < nodesCount; i++) {
for (int j = 0; j < nodesCount; j++) {
System.out.print(" " + netEdges[i][j] + " ");
}
System.out.println("");
}
}
public void putbeginNodeid(int beginNodeid) {
this.beginNodeid = beginNodeid;
}
public void putendNodeid(int endNodeid) {
this.endNodeid = endNodeid;
}
public void DijestraTagging() {
flagAndEdge[0][beginNodeid] = 1;
flagAndEdge[1][beginNodeid] = 0;
int tempMinLength = 10000;
int tempMinNode = 0;
int tempEx = 0;
int tempLengthEx = 0;
int maxPoach = nodesCount * nodesCount;
int k = 0;
while ((flagAndEdge[0][endNodeid] != 1) && (k <= maxPoach)) {
tempMinLength = 100000;
for (int i = 1; i <= nodesCount; i++) {// 下面这个for每次只标一个点
if (flagAndEdge[0][i] == 1) // 从表好了的结点找未标号的
{
tempEx = i;
tempLengthEx = flagAndEdge[1][i];
for (int j = 1; j <= nodesCount; j++) {
if (netEdges[i][j] > 0 && flagAndEdge[0][j] == 0) {
if (tempLengthEx + netEdges[i][j] < tempMinLength) {
tempMinLength = tempLengthEx + netEdges[i][j];
tempMinNode = j;
tempEx = i;
}
}
}
}
}
// 上面已经找出待标号的点了,下面只要求从哪些点可以以最短路径连接到该点 遍历netEdges[] flagAnddge
// 这样就可以存一个路径链接过来的 多个节点了
for (int j = 1; j <= nodesCount; j++) {
if (flagAndEdge[0][j] == 1 && netEdges[tempMinNode][j] > 0) {
if (netEdges[tempMinNode][j] + flagAndEdge[1][j] == tempMinLength
&& j != tempMinNode) {
nodes[tempMinNode].linkedExNodes.add(j);
}
}
}
flagAndEdge[0][tempMinNode] = 1;
flagAndEdge[1][tempMinNode] = tempMinLength;
flagAndEdge[2][tempMinNode] = tempEx;
flagAndEdge[3][tempMinNode]++;
if (nodes[tempMinNode].linkedExNodes.size() > 1) {
flagAndEdge[3][tempMinNode] = 1;// flagAndEdge[3][j]==1
// 表示有多个前节点
}
k++;
}
if (k > maxPoach) {
System.out.println("不存在从起始结点到终点的通路!");
return;
} else {
traceBack();
}
}
// String[] reversePaths = new String[nodesCount * nodesCount];
private void addOnepath(String path) {
int currentPathsCount = currentnthPath;
// System.out.println(" currentnthPath" + currentnthPath);
// System.out.println("path " + path);
reversePaths[currentnthPath] = path;
currentnthPath++;
// reversePaths[currentPathsCount] =new String(path);
}
private void traceFromOneNode(int i, String prepath) {
// if (i == beginNodeid && currentnthPath < 50) {
if (i == beginNodeid) {
addOnepath(prepath + i);
} else {
LinkedList<Integer> templl = (LinkedList<Integer>) nodes[i].linkedExNodes.clone();
while(templl.size()>0){
int tempint=templl.getFirst();
traceFromOneNode(tempint, prepath+i+" ");
templl.pop();
}
}
}
private String reverseAString(String oriStr){
StringBuffer sb=new StringBuffer();
for(int i=oriStr.length()-1;i>=0;i--){
sb.append(oriStr.charAt(i));
}
return sb.toString();
}
public void traceExNodes(){
for(int i=0;i<nodes.length;i++){
Node node=nodes[i];
Iterator it=node.linkedExNodes.iterator();
System.out.print("Exnodes of node"+i+": ");
while(it.hasNext()){
Integer in=(Integer) it.next();
System.out.print("\t "+in);
}
System.out.println(" ");
}
}
public void traceBack() {
// 深度优先 反向追踪 得到最短路径 ,以字符串形式表示,排序后, 然后 逆着输出字符串
// System.out.println("here to traceBack");
traceFromOneNode(endNodeid, "");
System.out.println(currentnthPath+" "+flagAndEdge[1][endNodeid]);
// 下面正着输出 路径
String[] orderPaths=new String[currentnthPath];
for(int i=0;i<currentnthPath;i++){
orderPaths[i]=reversePaths[i];
}
Arrays.sort(orderPaths);
for(int i=0;i<currentnthPath;i++){
System.out.println(reverseAString(reversePaths[i]));
}
// System.out.println("Shortest len:" + flagAndEdge[1][endNodeid]);
for (int i = 1; i <= nodesCount; i++) {
Iterator it = nodes[i].linkedExNodes.iterator();
// System.out.println("exNode" + i + ": ");
while (it.hasNext()) {
Integer n = (Integer) it.next();
// System.out.print(n);
}
// System.out.println("\r\n");
}
}
public void printPaths() {
}
}
class Node {
public String exNodesCount;
int nodeid;
int lenToBeginNode;
int[] preNodes;
LinkedList<Integer> linkedExNodes = new LinkedList<Integer>();
// int exNodesCount = linkedExNodes.size();
public int getexNodesCount() {
// System.out.println("here come to size"+exNodesCount);
return linkedExNodes.size();
// linkedExNodes.a
}
public Node(int nodeid) {
this.nodeid = nodeid;
}
public int getNodeid() {
return this.nodeid;
}
public int getLenToBeginNode() {
return this.lenToBeginNode;
}
public LinkedList getlinkedExNodes() {
return this.getlinkedExNodes();
}
}
下面是两个测试用例的数据:
测试数据一:
5 6
1 2 1
1 3 3
2 3 2
2 4 1
3 4 1
3 5 1
1 5
测试数据二:
5 8
2 1 2
1 5 2
2 3 5
2 4 6
2 5 5
3 4 1
3 5 1
4 5 2
2 4
注意使用Scanner的话最后一行的enter不能忘了哦……测试时把scannenr参数该为文件吧