HDU 3790 最短路径问题

最短路径问题

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 30385    Accepted Submission(s): 8985


Problem Description
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
 
Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
 
Output
输出 一行有两个数, 最短距离及其花费。
 
Sample Input
3 2 1 2 5 6 2 3 4 5 1 3 0 0
 
Sample Output
9 11
 
思路:也是一道入门的最短路问题,之前一直wa了,后面才想到某一条路径可能会重复出现,判断下取最小的就好了。
#include<iostream>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int M = 1009;
int n,m,vis[M],dist[M],ans[M],minn,g[M][M],i,j,u,a,b,d,p,s,e,v[M][M];
void dij(){
    for(i=0;i<=n;i++){
        dist[i] = INF;
        vis[i] = 0;
    }
    dist[s] = 0;
    ans[s] = 0;
    int n1 = n;
    while(n1--){
        int minn = INF;
        for(i=1;i<=n;i++){
            if(!vis[i]&&minn>dist[i]){
                minn = dist[i]; u = i;
            }
        }
        vis[u] = 1;
        for(i=1;i<=n;i++){
            if(!vis[i]&&dist[i]>dist[u]+g[u][i]){
                dist[i] = dist[u] + g[u][i];
                ans[i] = ans[u] + v[u][i];
            }
            else if(!vis[i]&&dist[i]==dist[u]+g[u][i]){
                ans[i] = min(ans[i],ans[u]+v[u][i]);
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    while(cin>>n>>m){
        memset(g,INF,sizeof(g));
        memset(v,INF,sizeof(v));
        if(n==0&&m==0) break;
        for(i=0;i<=n;i++){
            for(j=0;j<=n;j++){
                if(i==j) g[i][j] = 0;
                else g[i][j] = INF;
            }
        }
        for(i=1;i<=m;i++){
            cin>>a>>b>>d>>p;
            if(g[a][b]>=d){
            g[a][b] = g[b][a] = d;
            v[a][b] = v[b][a] = p;
            }
        }
        cin>>s>>e;
            dij();
            cout<<dist[e]<<" "<<ans[e]<<endl;
    }
}
原文地址:https://www.cnblogs.com/kls123/p/7773233.html