2013dgtcs 廉价最短路径
题目
问题描述:
图是由一组顶点和一组边组成的。一条边连接两个顶点。例如,图1表示了一个有4个顶点V、5条边的图。图中,每条边e是有方向的,方向从起点到终点,并且每条边都有价值。用整数0,1,…,m-1可以表示一个有m个顶点的图。
图1 图2
一条路径连接了一个点Vi和另一个点Vj,其方向与经过的一系列边的方向一致。路径的长度是途经边的条数,路径的费用是边价值的总和。对于一个给定的图,你的任务是在所有最短路径中,找出需要最少费用的连接V0和V1的路径。一个需要最少费用的最短路径称之为廉价最短路径。
让我们重新考虑图1,从0到1的最短路径是只含一条边的路径0→1,费用是10。当然,还有更便宜的路:0→2→1和 0→3→1,但是它们比第一条路径长(有2条边)。所以,0→1是廉价最短路径。
看一下另一个例子,图2,它有2条最短路径,其长度是2,路径0→3→1(费用=4)比路径0→2→1(费用=5)花费少。还用另一条路径0→2→3→1(费用=3),虽然便宜但是很长。所以,廉价最短路径是0→3→1。
数据输入
输入文件第一行有两个整数m和n,用一个空格隔开,其中,m是顶点数,而n是边数。接下来的n行给出所有的边及其价值,每行有3个整数(相邻两个整数间有一个空格),表示起点,终点和边的价值。顶点最多有100个,编号在0到99之间。边最多有1000条,其价值在0到215-1之间。
数据输出
输出文件仅有一行包含一个整数,即V0→V1的廉价最短路径的费用。当出现有多个廉价最短路径的情况时,它们的费用是一样的。
输入输出样例
paths.in
4 5
0 2 2
0 3 2
0 1 10
2 1 2
3 1 2
paths.out
10
分析
显然最短路,改改优先顺序就好了
代码
1 #include<iostream> 2 #include<cstring> 3 #include<queue> 4 #include<vector> 5 using namespace std; 6 int map[210][210]; 7 vector <int> f[200]; 8 int vis[210]; 9 int dis1[210],dis2[210]; 10 queue <int> q; 11 void spfa() 12 { 13 memset(vis,0,sizeof(vis)); 14 memset(dis1,0x1f,sizeof(dis1)); 15 memset(dis2,0x3f,sizeof(dis2)); 16 dis1[0]=0; dis2[0]=0; vis[0]=1; q.push(0); 17 while (!q.empty()) 18 { 19 int x=q.front(); q.pop(); vis[x]=0; 20 for (int i=0;i<f[x].size();i++) 21 { 22 int y=f[x][i]; 23 if (dis2[y]>dis2[x]+1) 24 { 25 dis1[y]=dis1[x]+map[x][y]; 26 dis2[y]=dis2[x]+1; 27 if (vis[y]==0) 28 { 29 vis[y]=1; 30 q.push(y); 31 } 32 } 33 if (dis2[y]==dis2[x]+1) 34 { 35 dis1[y]=min(dis1[y],dis1[x]+map[x][y]); 36 if (vis[y]==0) 37 { 38 vis[y]=1; 39 q.push(y); 40 } 41 } 42 } 43 } 44 } 45 int main() 46 { 47 int n,m; 48 cin>>n>>m; 49 for (int i=1,x,y,z;i<=m;i++) 50 { 51 cin>>x>>y>>z; 52 map[x][y]=z; 53 f[x].push_back(y); 54 } 55 spfa(); 56 cout<<dis1[1]; 57 return 0; 58 }