码迷,mamicode.com
首页 > 其他好文 > 详细

eoj1818 dijkstra求最短路及其条数

时间:2014-12-31 18:35:01      阅读:500      评论:0      收藏:0      [点我收藏+]

标签:eoj1818   dijkstra单源最短路的条数   最短路条数   

求出有n(1 < n <= 100)个结点有向图中,结点1到结点n的最短路径,以及最短路径的条数。

Input

第一行有2个整数n和m( 0 < m < 3000),接下来m行每行有三个整数u,v,w结点u到v之间有一条权为w的边(w<100000)。

Output

输出只有一行,为结点1到结点n之间的最短路径及其条数(用空格隔开),如果1到n之间不存在路径,输出 -1 0。

Sample Input

3 3

1 2 10

2 3 15

1 3 25

Sample Output

25 2

 

 

 

分析:本题中两相邻点间可能存在多条路,但每条路长度相同,这点在题中并没有说明。

思路:做两次dijkstra即可,第一次用于求出各点到源点的最短距离。第二次用于统计最短路条数。分两类统计:一类为最短路间没有中间定点的,另一类为最短路间有中间顶点的。

 

 

 

 

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;
int cost[101][101],path[101][101],low[101],dis[101],num[101]={};//low和dis数组分别是两次dijkstra的当前i点到源点的最短路
bool vis[101];                                                  //path保存两点间路径条数
const int MAXN=10000001;                                        //num保存点到源点最短路径数目

int main()
{
    int n,m,i,j,k;
    memset(vis,false,sizeof(vis));
    scanf("%d%d",&n,&m);
    for(i=0;i<101;++i){         //初始化代价矩阵
        for(j=0;j<101;++j){
            cost[i][j]=MAXN;
        }
    }
    for(i=0;i<m;++i){           //读数据
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        cost[a][b]=c;
        path[a][b]++;
    }
    vis[1]=true;                //第一次dijkstra求最短路
    for(i=2;i<=n;++i)
        low[i]=cost[1][i];
    for(i=2;i<=n;++i){
        int minn=MAXN+1;
        for(j=1;j<n;++j){
            if(!vis[j] && low[j]<minn){
                minn=low[j];k=j;
            }
        }
        vis[k]=true;
        for(j=1;j<=n;++j){
            if(!vis[j]){
                low[j]=min(low[j],low[k]+cost[k][j]);
            }
        }
    }
    memset(vis,false,sizeof(vis));
    vis[1]=true;                    //第二次dijkstra求最短路条数,最短路分两类,一类直达,一类借助中间点达
    for(i=2;i<=n;++i) dis[i]=cost[1][i];
    for(i=2;i<=n;++i)               //第一类直达
        if(dis[i]==low[i])
            num[i]=path[1][i];
    for(i=2;i<=n;++i){
        int minn=MAXN+1;
        for(j=1;j<=n;++j){
            if(!vis[j] && dis[j]<minn){
                minn=dis[j];k=j;
            }
        }
        vis[k]=true;
        for(j=1;j<=n;++j){
            if(!vis[j]){
                dis[j]=min(dis[j],dis[k]+cost[k][j]);
            }
            if(dis[k]+cost[k][j]==low[j])   //统计第二类,通过中间点到达的路径数目
                num[j]+=num[k]*path[k][j];
        }
    }
    if(low[n]>=MAXN)
        printf("-1 0\n");
    else
        printf("%d %d\n",low[n],num[n]);
    return 0;
}


eoj1818 dijkstra求最短路及其条数

标签:eoj1818   dijkstra单源最短路的条数   最短路条数   

原文地址:http://blog.csdn.net/fangpinlei/article/details/42296371

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!