您的位置:首页 > 其它

计算结点1到结点n的最短路径,以及最短路径的条数

2012-12-22 09:57 288 查看
Description

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

题目链接:http://acm.cs.ecnu.edu.cn/problem.php?problemid=1818

//计算最短路径的条数,总体思路是再写一遍类似dijikstra算法,进行统计
#include<stdio.h>
#define MAX 102
#define MAXN 1000000
int cost[MAX][MAX],dist[MAX],dist2[MAX],num[MAX][MAX]={0},ci[MAX]={0};  //dist2[]是在第二次写dijikstra时,记录最短路径长度,
int main()                                                              //存在重边的情况,num[][]记录重边的条数
{                                                                       //c[i]记录从点v到到i的最短路径条数
void dij(int n,int v);
void shortestpath(int n,int v);
int n,m,i,j,k,data;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)
{
cost[i][j]=0;
}
else
{
cost[i][j]=MAXN;
}
}
}
for(i=0;i<m;i++)
{
scanf("%d%d",&j,&k);
scanf("%d",&data);
cost[j][k]=data;
num[j][k]++;
}
shortestpath(n,1);
dij(n,1);
if(dist
<MAXN)
{
printf("%d %d\n",dist
,ci
);
}
else
{
printf("-1 0\n");
}
return 0;
}
//第一次应用dijikstra,计算最短路径,保存在dist[]中
void shortestpath(int n,int v)
{
int i,j,k,s[MAX],min;
for(i=1;i<=n;i++)
{
s[i]=0;
dist[i]=cost[v][i];
}
s[v]=1;
for(i=1;i<=n;i++)
{
k=0;
min=MAXN;
for(j=1;j<=n;j++)
{
if(s[j]==0)
{
if(dist[j]<min&&dist[j]!=0)
{
min=dist[j];
k=j;
}
}
}
if(k==0)
{
break;
}
s[k]=1;
for(j=1;j<=n;j++)
{
if(s[j]==0&&cost[k][j]<MAXN)
{
if(cost[k][j]+dist[k]<dist[j])
{
dist[j]=cost[k][j]+dist[k];
}
}
}
}
}
//第二次应用dijikstra,计算最短路径条数
void dij(int n,int v)
{
int i,s[MAX],j,k,min;
for(i=1;i<=n;i++)
{
s[i]=0;
dist2[i]=cost[v][i];
if(dist2[i]==dist[i])         //如果i到v之间存在直接通路且长度就是最短路径,c[i]=num[v][i]
{
ci[i]=num[v][i];
}
}
s[v]=1;
for(i=1;i<=n;i++)
{
k=0;
min=MAXN;
for(j=1;j<=n;j++)
{
if(s[j]==0&&dist2[j]<min&&dist2[j]!=0)
{
min=dist2[j];
k=j;
}
}
if(k==0)
{
break;
}
s[k]=1;
for(j=1;j<=n;j++)
{
if(dist2[k]+cost[k][j]<dist2[j])
{
dist2[j]=dist2[k]+cost[k][j];
}
if(dist2[k]+cost[k][j]==dist[j])        //重置c[i],如果以k为中间点,v到j的距离刚好是最短路径长度,那么c[i]需要重置
{
ci[j]=ci[k]*num[k][j]+ci[j];
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: