九度OJ题目1447:最短路径(Dijstra 算法)

题目描述:

在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

输入:

输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。输入保证至少存在1条商店到赛场的路线。当输入为两个0时,输入结束。

输出:

对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间。

样例输入:
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
样例输出:
3
2
/*Dijstra算法  
    一:是寻找特定点到其他所有节点的最短路径方法  
    二:很好的支持了邻接表,同样也支持邻接矩阵  
    三:时间复杂度为O(N*N) 若在查找最小值处进行堆优化可以达到O(N*logN)
 K集合为已经确定到特定节点最短路径长度的节点集合, U集合为整体集合出去K集合的部分*/  
  
#include   
#include  
using namespace std;  
  
//邻接链表中存储的结构。该结构理解起来不是单纯的边结构,  
//好像是一个 " ——0 " 一条边一端连接着一个节点的结构(这样更易理解)  
struct E{  
    int next;       //与该点相连的下一个点  
    int weight;     //与该点相连的下一个点之间的权值  
};  
  
vector edge[101];   //定义邻接链表(利用vector形成的二维数组,vector有动态增加的优点)  
bool mark[101];         //标记,mark[i]表示到i节点最短路径已经找到,i节点已经加入K集合  
  
int dis[101];           //当mark[i] = true 时dis[i]表示特定节点到达i节点的最短距离.否则表示  
                        //从节点1出发按照某条最短路径到达某已经在集合K中的点,并由该点经过一条边到达  
                        //节点i路径中最短距离。  (注意dis[i] 的不同含义)  
int main()  
{  
    int n,m;  
    while(scanf("%d%d", &n,&m) != EOF) {  
        if(n == 0 && m == 0) break;  
        //初始化邻接链表  
        for(int i=1;i<=n;i++) {  
            edge[i].clear();  
        }  
        //录入数据  
        while(m-- != 0) {  
            int p1, p2, weight;  
            scanf("%d%d%d", &p1, &p2, &weight);  
            E tmp;  
            tmp.weight = weight;  
            tmp.next = p1;  
            edge[p2].push_back(tmp);   //将边放到p2点对应的vector中  
            tmp.next = p2;  
            edge[p1].push_back(tmp);   //由于是无向图,所以也要将边放到  
        }  
        //初始化,所有节点不属于K集合,所有节点都是孤立的  
        for(int i=0;i<=n;i++) {  
            mark[i] = false;  
            dis[i] = -1;  
        }  
  
        //本题是找从1到N的最短路径,此处将节点1设为初始K集合成员  
        mark[1] = true;  
        dis[1] = 0;  
        int newP = 1;           //结合K中新加入的节点为1  
  
        for(int i=1;i<=n;i++) {  //经过n-1次循环找到从特定节点到其他n-1个节点的最短路径  
  
             /*遍历新加入节点的所有相邻节点,  
               计算并更新新加入集合的相邻节点与1节点之间的距离*/  
            for(int j=0;j dis[newP] + weight) {  
                    dis[next] = dis[newP] + weight;  
                }  
            }  
  
            int min = 99999999;  
            /*遍历所有节点,在节点1经K集合 到达 U集合已经计算出与1节点之间距离的节点之中找到距离最小的  
            边作为下一个加入K集合的新节点  (简单点说:即在U集合中找newP)  
            */  
            for(int j=1;j<=n;j++) {  
                if(mark[j] == true) continue;   //已经在K集合中跳过  
                if(dis[j] == -1) continue;      //还未计算出与1节点之间的距离的跳过  
                if(dis[j] < min) {  
                    min = dis[j];  
                    newP = j;  
                }  
            }  
            mark[newP] = true;  
        }  
        printf("%d\n", dis[n]);  
  
    }  
    return 0;  
}  

我的 Floyd算法 请参考http://blog.csdn.net/qq_31820885/article/details/61919979

你可能感兴趣的:(Algorithm)