Floyd算法:用动态规划求解多源(全源)最短路径

来源:互联网 发布:ubuntu原版和麒麟 编辑:程序博客网 时间:2024/06/01 08:54

loyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3)。

    Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B。所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,我们便设置Dis(AB) = Dis(AX) + Dis(XB),这样一来,当我们遍历完所有节点X,Dis(AB)中记录的便是A到B的最短路径的距离。

  但是这里我们要注意循环的嵌套顺序,如果把检查所有节点X放在最内层,那么结果将是不正确的,为什么呢?因为这样便过早的把i到j的最短路径确定下来了,而当后面存在更短的路径时,已经不再会更新了。

for(int k=0; k<vexnum; ++k)          for(int i=0; i<vexnum; ++i)              for(int j=0; j<vexnum; ++j)                  if( dist[i][j] > dist[i][k]+dist[k][j] )                  {                      dist[i][j] = dist[i][k] + dist[k][j];                      path[i][j] = path[k][j];                  }  } 


做了一道谷歌算法题,题目很简单。

Problem

Company G has a main campus with N offices (numbered from 0 to N - 1) and Mbidirectional roads (numbered from 0 to M - 1). The ith road connects a pair of offices (Ui, Vi), and it takes Ci minutes to travel on it (in either direction).

A path between two offices X and Y is a series of one or more roads that starts at X and ends at Y. The time taken to travel a path is the sum of the times needed to travel each of the roads that make up the path. (It's guaranteed that there is at least one path connecting any two offices.)

Company G specializes in efficient transport solutions, but the CEO has just realized that, embarrassingly enough, its own road network may be suboptimal! She wants to know which roads in the campus are inefficient. A road is inefficient if and only if it is not included in any shortest paths between any offices.

Given the graph of offices and roads, can you help the CEO find all of the inefficient roads?

Input

The first line of the input gives the number of test cases, TT test cases follow. Each case begins with one line with two integers N and M, indicating the number of offices and roads. This is followed by M lines containing three integers each: UiVi and Ci, indicating the ith road is between office Ui and office Vi, and it takes Ci minutes to travel on it.

Output

For each test case, output one line containing "Case #x:", where x is the test case number (starting from 1). Then output the road numbers of all of the inefficient roads, in increasing order, each on its own line. (Note that road 0 refers to the first road listed in a test case, road 1 refers to the second road, etc.)

Limits

0 < Ci ≤ 1000000.

Small dataset

1 ≤ T ≤ 10.
1 ≤ N = M ≤ 100.

Large dataset

1 ≤ T ≤ 3.
1 ≤ N ≤ 100.
1 ≤ M ≤ 10000.

Sample


Input 
 
Output 
 
23 30 1 101 2 32 0 33 30 1 101 2 32 1 3
Case #1:0Case #2:
可用Floyd算法求解:

package google;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.util.Arrays;import java.util.List;import java.util.ArrayList;public class gCampus1 {public static void main(String [] args){try {              FileReader inf = new FileReader("C-large-practice.in");              BufferedReader in = new BufferedReader(inf);            BufferedWriter out=new BufferedWriter(new FileWriter("out.txt"));            int n = Integer.parseInt(in.readLine());            for(int i = 1;i <= n;i++){            String [] kk = in.readLine().split(" ");            int vn = Integer.parseInt(kk[0]);            int [][] a = new int[vn][vn];            int [][] a_r = new int[vn][vn];            int mn = Integer.parseInt(kk[1]);            boolean[] roads = new boolean[mn];            int [] t1 = new int[mn];            int [] t2 = new int[mn];            int [] t3 = new int[mn];            Arrays.fill(roads,false);            for(int k = 0;k < vn;k++){            for(int j = 0;j < vn;j++){            if(a[k][j] == 0 && k != j){            a[k][j] = 900000000;            }            }            }            for(int j = 0;j < mn;j++){            String []temp = in.readLine().split(" ");            int v1 = Integer.parseInt(temp[0]);            int v2 = Integer.parseInt(temp[1]);            int len = Integer.parseInt(temp[2]);            t1[j] = v1;            t2[j] = v2;            t3[j] = len;            if(a[v1][v2] < len){            roads[j] = true;            System.out.println(len+" ");            continue;            }            //if(a[v1][v2] == 0 || a[v1][v2] > len){            a[v1][v2] = len;            a[v2][v1] = len;            a_r[v1][v2] = j;            a_r[v2][v1] = j;            //}            }            /*boolean [] visit = new boolean [vn];            Arrays.fill(visit, false);            visit[0] = true;            List<Integer> re = new ArrayList<Integer>();            DijkstraPath(a,0,a_r,re,visit);            for(int j = 0;j < re.size();j++){            roads[(int)re.get(j)] = true;            for(int k = 0;k < vn;k++){                        }            }*/            for(int k = 0;k < vn;k++){            for(int j = 0;j < vn;j++){            for(int h = 0;h < vn;h++){            a[j][h] = Math.min(a[j][h], a[j][k]+a[k][h]);            }            }            }                        for(int j = 0;j < mn;j++){            if(t3[j] > a[t1[j]][t2[j]]){            roads[j] = true;            }            }            out.write("Case #" + i + ":");            for(int j = 0;j < mn;j++){            if(roads[j]){            out.newLine();;            out.write(String.valueOf(j));            }            }            out.newLine();            }          in.close();          out.close();  }catch(Exception e){System.out.println("error");}}public static void DijkstraPath(int [][] a, int v0, int [][] a_r,List<Integer> re,boolean []visit){int n = a.length;if(v0 >= n-1){return;}int [] dist = new int [n];int [] last = new int [n];Arrays.fill(dist, -1);Arrays.fill(last, -1);Arrays.fill(visit, v0+1, n, false);int count  = 1;dist[v0] = 0;visit[v0] = true;for(int i = 0 ;i < n;i++){if(a[v0][i] > 0){dist[i] = a[v0][i];last[i] = v0;}}while(count < n){int target = -1;int min = Integer.MAX_VALUE;for(int i = 0;i < n;i++){if(!visit[i] && i!=v0 && dist[i] != -1 && dist[i] < min){min = dist[i];target = i;}}if(target == -1){break;}re.add(a_r[last[target]][target]);if(target != -1){visit[target] = true;count++;for(int i = 0;i < n;i++){if(i != target && !visit[i] && a[target][i] > 0){if(dist[i] < 0){dist[i] = a[target][i];last[i] = target;}else if(dist[i] > dist[target] + a[target][i]){dist[i] = dist[target] + a[target][i];last[i] = target;}}}}}DijkstraPath(a,v0+1,a_r,re,visit);}}




0 0
原创粉丝点击