一看到题就想到Dijkstra了。。但是突然看到两个权值懵逼了,看到讨论里面的大佬的代码才醒悟。
题目输入比较坑的一点是,前面输入的边的距离和花费,到后面可能会变,比如前面输入了 1 2 8 6,后面又输入 2 1 2 9这种。
所以在读入数据的时候(makeG函数),要判断一下。
Dijkstra没啥好说的,就是在更新的时候不同于传统的算法,首先是判断距离是不是更小,之后如果距离是相等的而花费更小,也要更新。(这就是一开始懵的地方了。。)
因为不要求输出源到汇的完整路径,所以不用path了,只保存dist和cost即可。
#include<stdio.h>
#include<limits.h>
#define NMAX 1001
int n,m;
int disG[NMAX][NMAX]; // 距离图
int costG[NMAX][NMAX]; // 花费图
int dis[NMAX]; // 源点到各点的距离
int cost[NMAX]; // 源点到各点的花费
int visit[NMAX]; // 当前结点是否遍历过

void init()
{
    for(int i = 1;i<=n;i++)
    {
        for (int j = 1; j <= n; j++)
        {
            disG[i][j] = i == j ? 0 : INT_MAX;
            costG[i][j] = i == j ? 0 : INT_MAX;
        }
        dis[i] = INT_MAX;
        cost[i] = INT_MAX;
        visit[i] = 0;
    }
    return;
}
void makeG()
{
    int x,y,dis,cost;
    for(int i = 0;i<m;i++)
    {
        scanf("%d %d %d %d",&x,&y,&dis,&cost);
        if(dis < disG[x][y]) // 如果当前输入的距离比原本更小则更新
        {
            disG[x][y] = dis;
            disG[y][x] = dis;
            costG[x][y] = cost;
            costG[y][x] = cost;
        }
        else if(dis == disG[x][y] && cost < costG[x][y]) // 如果距离相等而花费更小则更新
        {
            costG[x][y] = cost;
            costG[y][x] = cost;
        }
    }
}
int findminv() // 找出当前未遍历过的点且距离最短
{
    int min = INT_MAX;
    int minv = -1;
    for(int i = 1;i<=n;i++)
    {
        if(!visit[i] && dis[i] < min)
        {
            min = dis[i];
            minv = i;
        }
    }
    if(min < INT_MAX)
        return minv;
    else
        return -1;
}
void Dijkstra(int s)
{
    int minv;
    visit[s] = 1;
    for(int i = 1;i<=n;i++) // 把图的距离和花费数据更新到dis和cost中以便findminv
    {
        if(disG[s][i]!=INT_MAX)
        {
            dis[i] = disG[s][i];
            cost[i] = costG[s][i];
        }
    }
    while(1)
    {
        minv = findminv();
        if(minv == -1) // 全部遍历完
            break;
        else
        {
            visit[minv] = 1;
            for(int i = 1;i<=n;i++)
            {
                if(!visit[i] && disG[minv][i] < INT_MAX)
                {
                    if(dis[minv] + disG[minv][i] < dis[i]) // 距离更短
                    {
                        dis[i] = dis[minv] + disG[minv][i];
                        cost[i] = cost[minv] + costG[minv][i];
                    }
                    else if(dis[minv] + disG[minv][i] == dis[i] && cost[minv] + costG[minv][i] < cost[i])// 距离相等且花费更小
                        cost[i] = cost[minv] + costG[minv][i];
                }
            }
        }
    }

}
int main()
{
    int s,t;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        if(n == 0 && m == 0)
            break;
        init();
        makeG();
        scanf("%d %d", &s, &t);
        Dijkstra(s);
    }
    printf("%d %d\n",dis[t],cost[t]);
    return 0;
}