最短路经典例题 codevs 1557 热浪

codevs 1557 热浪

题目描述:
德克萨斯纯朴的民眾们这个夏天正在遭受巨大的热浪!!!他们的德克萨斯长角牛吃起来不错,可是他们并不是很擅长生產富含奶油的乳製品。Farmer John此时以先天下之忧而忧,后天下之乐而乐的精神,身先士卒地承担起向德克萨斯运送大量的营养冰凉的牛奶的重任,以减轻德克萨斯人忍受酷暑的痛苦。
FJ已经研究过可以把牛奶从威斯康星运送到德克萨斯州的路线。这些路线包括起始点和终点先一共经过T(1<=T<=2500)个城镇,方便地标号為1到T。除了起点和终点外地每个城镇由两条双向道路连向至少两个其它地城镇。每条道路有一个通过费用(包括油费,过路费等等)。
给定一个地图,包含C(1<=C<=6200)条直接连接2个城镇的道路。每条道路由道路的起点Rs,终点Re(1<=Rs<=T;1<=Re<=T),和花费(1<=Ci<=1000)组成。求从起始的城镇Ts(1<=Ts<=T)到终点的城镇Te(1<=Te<=T)最小的总费用。
输入描述:
第一行: 4个由空格隔开的整数: T, C, Ts, Te
第2到第C+1行: 第i+1行描述第i条道路。有3个由空格隔开的整数: Rs, Re和Ci
输出描述:
一个单独的整数表示从Ts到Te的最小总费用。数据保证至少存在一条道路。
样例输入:
7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1
样例输出:
7
数据范围及提示:
5->6->1->4(3+1+3)

提供三种解法:
1、Floyed算法

#include<iostream>
using namespace std;
const int maxn=999999;
int T,C,ts,te;
int dis[2501][2501],x,y,z;
int main()
{
    cin>>T>>C>>ts>>te;
    for(int i=1;i<=T;i++)
      for(int j=1;j<=T;j++)
      dis[i][j]=maxn;
    for(int i=1;i<=C;i++)
    {
        cin>>x>>y>>z;
        dis[x][y]=dis[y][x]=z;
    }
    for(int k=1;k<=T;k++)
      for(int i=1;i<=T;i++)
        if(k!=i)
        for(int j=1;j<=T;j++)
        if(i!=j&&k!=j&&dis[i][j]>dis[i][k]+dis[k][j])
        dis[i][j]=dis[i][k]+dis[k][j];
    cout<<dis[ts][te];
    return 0;
}

因为数据太大,会超时!
总时间耗费: 3309ms
总内存耗费: 24 MB
这里写图片描述
2、Dijkstra算法
邻接矩阵版

#include<iostream>
using namespace std;
const int maxn=999999;
int T,C,ts,te;
int dis[10000],a[2510][2510];//在空间允许的范围内,dis[]数组尽量开大,否则会出错,不知为什么。。。 
int x,y,z,k,minn;
bool flag[10000];
int main()
{
    cin>>T>>C>>ts>>te;
    for(int i=1;i<=C;i++)
    {
        cin>>x>>y>>z;
        a[x][y]=a[y][x]=z;
        dis[i]=maxn;
    }
    dis[ts]=0;
    for(int i=1;i<=T;i++)
    {
        minn=maxn;
        k=0;
        for(int j=1;j<=T;j++)
        if(!flag[j]&&dis[j]<minn)
        {
            minn=dis[j];
            k=j;
        }
        if(k==0) break;
        flag[k]=true;
        for(int j=1;j<=T;j++)
        if(!flag[j]&&a[k][j]&&dis[j]>dis[k]+a[k][j])
        dis[j]=dis[k]+a[k][j];
    }
    cout<<dis[te];
    return 0;
}

总时间耗费: 139ms
总内存耗费: 20 MB
这里写图片描述
邻接链表版

#include<iostream>
using namespace std;
const int maxn=1000001;
struct node
{
    int to;
    int w;
    int next;
}e[maxn];
int n,m,tot,minn,k,dis[maxn],head[maxn];
int qi,zhong;
bool flag[maxn];
void edd_edge(int u,int v,int w)
{
    tot++;
    e[tot].to=v;
    e[tot].w=w;
    e[tot].next=head[u];
    head[u]=tot;
}
int main()
{
    int x,y,z;
    cin>>n>>m>>qi>>zhong;
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y>>z;
        edd_edge(x,y,z);
        edd_edge(y,x,z);
    }
    for(int i=1;i<=n;i++)
    dis[i]=maxn;
    dis[qi]=0;
    for(int i=1;i<=n;i++)
    {
        minn=maxn;
        k=0;
        for(int j=1;j<=n;j++)
        if(!flag[j]&&minn>dis[j])
        {
            minn=dis[j];
            k=j;
        }
        flag[k]=1;
        for(int j=head[k];j;j=e[j].next)
        if(!flag[e[j].to]&&dis[e[j].to]>dis[k]+e[j].w)
        dis[e[j].to]=dis[k]+e[j].w;
    }
    cout<<dis[zhong];
    return 0;
}

总时间耗费: 67ms
总内存耗费: 492 kB
这里写图片描述
3、SPFA算法
因为使用了邻接矩阵,所以并没有发挥SPFA算法的优势,竟然不如Dijkstra快。。。
邻接矩阵版

#include<iostream>
using namespace std;
const int maxn=1000000;
int T,C,ts,te;
int dis[10000],a[2501][2501];
int x,y,z,u,team[10001],head,tail=1;
bool exsit[2501];
int main()
{
    cin>>T>>C>>ts>>te;
    for(int i=1;i<=C;i++)
    {
        cin>>x>>y>>z;
        a[x][y]=a[y][x]=z;
        dis[i]=maxn;
    }
    dis[ts]=0;
    team[1]=ts;
    while(head<tail)
    {
        head++;
        u=team[head];
        exsit[u]=false;
        for(int j=1;j<=T;j++)
        if(dis[j]>dis[u]+a[u][j]&&a[u][j])
        {
            dis[j]=dis[u]+a[u][j];
            if(!exsit[j])
            {
                tail++;
                team[tail]=j;
                exsit[j]=true;
            }
        }
    }
    cout<<dis[te];
    return 0;
}

总时间耗费: 160ms
总内存耗费: 20 MB
这里写图片描述
邻接链表版

#include<iostream>
#include<queue>
using namespace std;
const int maxn=1000001;
struct node
{
    int to;
    int w;
    int next;
}e[maxn];
queue<int> q;
bool flag[maxn];
int n,m,qi,zhong,tot,head[maxn],dis[maxn];
void edd_edge(int u,int v,int w)
{
    tot++;
    e[tot].to=v;
    e[tot].w=w;
    e[tot].next=head[u];
    head[u]=tot;
}
int main()
{
    int x,y,z;
    cin>>n>>m>>qi>>zhong;
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y>>z;
        edd_edge(x,y,z);
        edd_edge(y,x,z);
    }
    for(int i=1;i<=n;i++)
    dis[i]=maxn;
    dis[qi]=0;
    q.push(qi);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        flag[u]=0;
        for(int j=head[u];j;j=e[j].next)
        if(dis[e[j].to]>dis[u]+e[j].w)
        {
            dis[e[j].to]=dis[u]+e[j].w;
            if(!flag[e[j].to])
            {
                q.push(e[j].to);
                flag[e[j].to]=1;
            }
        }
    }
    cout<<dis[zhong];
    return 0;
}

总时间耗费: 20ms
总内存耗费: 488 kB
这里写图片描述

原文地址:https://www.cnblogs.com/cax1165/p/6071018.html