hdu 3790 最短路径问题

最短路径问题

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


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
 
Source
 
思路:此题为最短路径水题,将采用不同算法来进行练习,Floyd运行超时可以理解,第一个算法用cin就超时,hdu是不是对C++有歧视啊?????
  • Dijkstra算法:

 

#include<cstdio>
#include<climits>
#include<iostream>
using namespace std;
int len[1005], mon[1005], vis[1005];
int mapp[1005][1005], mapd[1005][1005];
int n, m;
void dijkstra(int s)
{
    memset(vis, 0, sizeof(vis));

    for (int i = 1; i <= n; i++){
        len[i] = mapd[s][i];
        mon[i] = mapp[s][i];
    }

    vis[s] = 1; len[s] = mon[s] = 0;
    for (int i = 1; i < n; i++){

        int min = INT_MAX, p = 1;
        for (int j = 1; j <= n; j++){
            if (min > len[j] && vis[j] == 0){
                min = len[j];
                p = j;
            }
        }

        vis[p] = 1;
        for (int j = 1; j <= n; j++){
            if (len[p] + mapd[p][j] < len[j] && vis[j] == 0){
                len[j] = len[p] + mapd[p][j];
                mon[j] = mon[p] + mapp[p][j];
            }
            else if (len[p] + mapd[p][j] == len[j] && vis[j] == 0){
                if (mon[p] + mapp[p][j] < mon[j])
                    mon[j] = mon[p] + mapp[p][j];
            }
        }
    }
}
int main()
{

    while (cin >> n >> m, n&&m){

        for (int i = 0; i <= n; i++)
        for (int j = 0; j <= n; j++)
            mapd[i][j] = mapp[i][j] = 999999;


        for (int i = 0; i < m; i++){
            int a, b, d, p;
            //cin >> a >> b >> d >> p;
            scanf("%d%d%d%d", &a, &b, &d, &p);

            if (d < mapd[a][b]) {
                mapd[a][b] = mapd[b][a] = d;
                mapp[a][b] = mapp[b][a] = p;
            }
            else if (mapd[a][b] == d&&mapp[a][b] > p){
                mapp[a][b] = mapp[b][a] = p;
            }
        }

        int s, t; cin >> s >> t;
        dijkstra(s);
        cout << len[t] << " " << mon[t] << endl;
    }
    return 0;
}

 

  • 不知道叫什么名字的算法:
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;
int len[1005], mon[1005];
struct Node{
    int a, b, d, p;
};
vector<Node>way;
int main()
{
    int n, m;
    while (cin >> n >> m, n&&m){
        way.clear();              //很重要
        for (int i = 0; i < m; i++){
            Node temp;
            //cin >> temp.a >> temp.b >> temp.d >> temp.p;
            scanf("%d%d%d%d", &temp.a, &temp.b, &temp.d, &temp.p);
            way.push_back(temp);
        }
        int s, t; cin >> s >> t;


        //memset(len, 125, sizeof(len));
        //memset(mon, 125, sizeof(mon));
        for (int i = 0; i <= n; i++){
            len[i] = mon[i] = 999999;
        }
        len[s] = 0; mon[s] = 0;
        int flag = 1;
        while (flag){
            flag = 0;
            for (int i = 0; i < way.size(); i++){
                int a = way[i].a, b = way[i].b, d = way[i].d, p = way[i].p;
                if (len[a] + d < len[b]){
                    flag = 1;
                    len[b] = len[a] + d;
                    mon[b] = mon[a] + p;
                }
                else if (len[a] + d == len[b] && mon[a] + p < mon[b]){
                    flag = 1;
                    mon[b] = mon[a] + p;
                }
                if (len[b] + d < len[a]){
                    flag = 1;
                    len[a] = len[b] + d;
                    mon[a] = mon[b] + p;
                }
                else if (len[b] + d == len[a] && mon[b] + p < mon[a]){
                    flag = 1;
                    mon[a] = mon[b] + p;
                }

            }
        }
        cout << len[t] << " " << mon[t] << endl;
    }
    return 0;
}
  •  Floyd算法:
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
using namespace std;
int mapd[1005][1005], mapp[1005][1005];
int main()
{

    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++){
        mapp[i][j] = 9999;
        mapd[i][j] = 9999;
    }
    for (int i = 0; i < m; i++){
        int a, b, d, p;
        //cin >> a >> b >> d >> p;
        scanf("%d%d%d%d", &a, &b, &d, &p);
        mapd[a][b] = mapd[b][a] = d;
        mapp[a][b] = mapp[b][a] = p;
        
    }

    for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
    for (int k = 1; k <= n; k++){

        if (mapd[i][k] + mapd[k][j] < mapd[i][j]){
            mapd[i][j] = mapd[i][k] + mapd[k][j];
            mapp[i][j] = mapp[i][k] + mapp[k][j];
        }
        else if (mapd[i][k] + mapd[k][j] == mapd[i][j]){
            if (mapp[i][k] + mapp[k][j] < mapp[i][j])
                mapp[i][j] = mapp[i][k] + mapp[k][j];
        }

    }


    int s, t;
    while (cin >> s >> t, s&&t){
        cout << mapd[s][t] << " " << mapp[s][t] << endl;
    }
    return 0;
}

 

 

 今天先到这里,感谢昨天前女友送的一箱三只松鼠;

  • bellman-ford算法(虽然没有AC,不知道毛病在哪):

 

#include<cstdio>
#include<cmath>
#include<iostream>
using namespace std;
int n, m;
typedef struct Edge{
    int a, b, d, p;
}Edge;
Edge edge[100005];
int len[1005], mon[1005];
bool Bellman_ford(int s)
{
    for (int i = 1; i <= n; i++){
        len[i] = 9999999;
        mon[i] = 9999999;
    }
    len[s] = mon[s] = 0;

    for (int i = 1; i <= n - 1; i++)
    for (int j = 1; j <= m; j++){
        if (len[edge[j].b]>len[edge[j].a] + edge[j].d){
            len[edge[j].b] = len[edge[j].a] + edge[j].d;
            mon[edge[j].b] = mon[edge[j].a] + edge[j].p;
        }
        else if (len[edge[j].b] == len[edge[j].a] + edge[j].d){
            if (mon[edge[j].b]>len[edge[j].a] + edge[j].p)
                mon[edge[j].b] = mon[edge[j].a] + edge[j].p;
        }
        
        if (len[edge[j].a]>len[edge[j].b] + edge[j].d){
            len[edge[j].a] = len[edge[j].b] + edge[j].d;
            mon[edge[j].a] = mon[edge[j].b] + edge[j].p;
        }
        else if (len[edge[j].a] == len[edge[j].b] + edge[j].d){
            if (mon[edge[j].a]>len[edge[j].b] + edge[j].p)
                mon[edge[j].a] = mon[edge[j].b] + edge[j].p;
        }
        
    }
    bool flag = true;
    /*
    for (int i = 1; i <= m; i++){
        if (len[edge[i].b] > len[edge[i].a] + edge[i].d){
            flag = false;
            break;
        }
    }
    */
    return flag;
}
int main()
{
    while (cin >> n >> m, n&&m){

        for (int i = 1; i <= m; i++)
            scanf("%d%d%d%d", &edge[i].a, &edge[i].b, &edge[i].d, &edge[i].p);
        
        int s, t; cin >> s >> t;
        if (Bellman_ford(s))
            cout << len[t] << " " << mon[t] << endl;
    }
    
    return 0;
}

 

#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<iostream>
using namespace std;
const int MAX = 200002;
int n, m;
struct Node{
    int to;
    int cost;
    int mon;
    Node(int a, int b, int c) :to(a), cost(b), mon(c){}
};
vector<Node>vec[MAX];
bool vis[MAX] = { false };
long dis[MAX], mon[MAX];
void spfa(int s)
{
    for (int i = 0; i <= n; i++){
        vis[i] = false;
        dis[i] = INT_MAX;
        mon[i] = INT_MAX;
    }
    dis[s] = mon[s] = 0;
    queue<int>que;
    que.push(s);
    while (!que.empty()){
        int p = que.front();
        que.pop();
        vis[p] = false;
        for (int i = 0; i < vec[p].size(); i++){
            Node no = vec[p][i];

            if (dis[no.to]>dis[p] + no.cost){
                dis[no.to] = dis[p] + no.cost;
                mon[no.to] = mon[p] + no.mon;
                if (!vis[no.to]){
                    que.push(no.to);
                    vis[no.to] = true;
                }
            }
            else if (dis[no.to] == dis[p] + no.cost){
                if (mon[no.to] > mon[p] + no.mon){
                    mon[no.to] = mon[p] + no.mon;
                    if (!vis[no.to]){
                        que.push(no.to);
                        vis[no.to] = true;
                    }
                }
            }
        }
    }
    
}
int main()
{
    while (cin >> n >> m, n&&m){

        for (int i = 0; i < m; i++){
            int a, b, d, p;
            //cin >> a >> b >> d >> p;
            scanf("%d%d%d%d", &a, &b, &d, &p);
            vec[a].push_back(Node(b, d, p));
            vec[b].push_back(Node(a, d, p));
        }
        int s, t; cin >> s >> t;
        spfa(s);
        cout << dis[t] << " " << mon[t] << endl;
    }
    
    return 0;
}

 

 后面两种算法心好累,我要换个水题在试试了,baibaibaibai

 
posted @ 2018-04-15 21:06  我只有一件白T恤  阅读(222)  评论(0编辑  收藏  举报