链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790
这一题是一道双权值的问题,并且权值有主要与次要之分,这里我们仍采用dijkstra算法,不过在建图的时候我们需要多保存一条信息,就是第二个权值,在表示源点到目标点的代价的时候我们用一个二维数组来保存。然后更新的时候每个点仍只访问一次,可以保证最后结果的正确性,这里就不说其证明了(证明很简单)
代码如下:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define INF 10000000
const int maxn = 1005 ;
struct Node
{
int x ;
int in ;
int y ;
};
int dist[maxn][2] ;
int map[maxn][maxn][2] ;
int vis[maxn] ;
int n ;
int m ;
int s ;
int t ;
void init() ;
bool operator<(Node a , Node b)
{
if(a.x != b.x )
return a.x > b.x ;
return a.y > b.y ;
}
void dijkstra(int ) ;
int main()
{
int i ;
int p ;
int q ;
int w ;
int x ;
//freopen("data.in" , "r" , stdin) ;
while(scanf("%d%d" , &n , &m)!=EOF &&(m!=0 && n!=0))
{
init() ;
for(i = 1 ; i <= m ; i ++)
{
scanf("%d%d%d%d" ,&p , &q ,&w , &x) ;
if(map[p][q][0] > w )
{
map[p][q][0] = w ;
map[p][q][1] = x ;
map[q][p][0] = w ;
map[q][p][1] = x ;
}
else if(map[p][q][0]== w && map[p][q][1] > x)
{
map[p][q][0] = w ;
map[p][q][1] = x ;
map[q][p][0] = w ;
map[q][p][1] = x ;
}
}
scanf("%d%d" , &s , &t) ;
dijkstra(s) ;
printf("%d %d\n" , dist[t][0] , dist[t][1]) ;
}
return 0;
}
void init()
{
int i ;
int j ;
for(i = 0 ; i < maxn ; i ++)
{
dist[i][0] = INF ;
vis[i] = 0 ;
for( j = 0 ; j < maxn ; j ++)
{
map[i][j][0] = INF ;
map[i][j][1] = 0 ;
}
}
}
void dijkstra(int s)
{
int i ;
Node a ;
Node b ;
priority_queue<Node> Q ;
dist[s][0] = 0 ;
dist[s][1] = 0 ;
a.x = 0 ;
a.y = 0 ;
a.in = s ;
Q.push(a) ;
while(!Q.empty())
{
a = Q.top() ;
Q.pop() ;
if(vis[a.in])
continue ;
vis[a.in] ++ ;
for(i = 1 ; i <= n ; i ++)
{
if(!vis[i] && map[a.in][i][0] < INF && map[a.in][i][0] + a.x < dist[i][0])
{
dist[i][0] = map[a.in][i][0] + a.x ;
dist[i][1] = map[a.in][i][1] + a.y ;
b.x = dist[i][0] ;
b.y = dist[i][1] ;
b.in = i ;
Q.push(b) ;
}
else if(!vis[i] && map[a.in][i][0] < INF && map[a.in][i][0] + a.x == dist[i][0]
&& map[a.in][i][1] + a.y < dist[i][1])
{
dist[i][1] = map[a.in][i][1] + a.y ;
b.x = dist[i][0] ;
b.y = dist[i][1] ;
b.in = i ;
Q.push(b) ;
}
}
}
}