数据结构实验之图论七:驴友计划

数据结构实验之图论七:驴友计划

Time Limit: 1000MS Memory limit: 65536K

题目描述

做为一个资深驴友,小新有一张珍藏的自驾游线路图,图上详细的标注了全国各个城市之间的高速公路距离和公路收费情况,现在请你编写一个程序,找出一条出发地到目的地之间的最短路径,如果有多条路径最短,则输出过路费最少的一条路径。

输入

连续T组数据输入,每组输入数据的第一行给出四个正整数N,M,s,d,其中N(2 <= N <= 500)是城市数目,城市编号从0~N-1,M是城市间高速公路的条数,s是出发地的城市编号,d是目的地的城市编号;随后M行,每行给出一条高速公路的信息,表示城市1、城市2、高速公路长度、收费额,中间以空格间隔,数字均为整数且不超过500,输入数据均保证有解。 

输出

在同一行中输出路径长度和收费总额,数据间用空格间隔。 

示例输入

1
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

示例输出

3 40

提示

 

来源

xam 

示例程序

 解法一:(Floyd算法)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define Max 100000000
int main()
{
    int n,m,i,j,k,x,y,t,p,s,e,l;
    int code[510][510],dis[510][510];
    scanf("%d",&l);
    while(l--)
    {
        scanf("%d %d %d %d",&n,&m,&s,&e);
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
            if(i==j)
            {
                code[i][j]=0;
                dis[i][j]=0;
            }
        else
            {
                code[i][j]=Max;
                dis[i][j]=Max;
            }
        for(i=1;i<=m;i++)
        {
            scanf("%d %d %d %d",&x,&y,&t,&p);
            if(code[x][y]>t)
            {
                code[x][y]=t;
                code[y][x]=t;
                dis[x][y]=p;
                dis[y][x]=p;
            }
        }
        for(i=s;i<=e;i++)
        {
            for(j=s;j<=e;j++)
            {
                for(k=s;k<=e;k++)
                {
                    if(code[j][k]>(code[i][j]+code[i][k])||(code[j][k]==(code[i][j]+code[i][k])&&dis[j][k]>(dis[i][j]+dis[i][k])))
                       {
                        code[j][k]=code[i][j]+code[i][k];
                        dis[j][k]=dis[i][j]+dis[i][k];

                       }
                }
            }
        }
        printf("%d %d\n",code[s][e],dis[s][e]);
    }
    return 0;
}


解法二:(Dijkstra算法)

#include<stdio.h>
#include<string.h>
#define INF 65535
struct node
{
    int a,b;
} map[1005][1005];;
int p[10010],final[1010],d[1000],d1[1010],s;
int n,m;
void Dijkstra()
{
    int v,w,k,min,mi;
    for(v=1;v<=n;v++)
    {
        final[v]=0;
        d[v]=map[s][v].a;
        d1[v]=map[s][v].b;
        p[v]=0;
    }
    d[s]=0;
    d1[s]=0;
    final[s]=1;
    for(v=2;v<=n;v++)
    {
        min=INF;
        mi=INF;
        for(w=1;w<=n;w++)
        {
            if(!final[w]&&(d[w]<min)||(d[w]==min&&mi>d1[w]))
            {
                k=w;
                min=d[w];
                mi=d1[w];
            }
        }
        final[k]=1;
        for(w=1;w<=n;w++)
        {
            if(!final[w]&&(min+map[k][w].a<d[w]||(min+map[k][w].a==d[w]&&mi+map[k][w].b<d1[w])))
            {
                d[w]=min+map[k][w].a;
                d1[w]=mi+map[k][w].b;
                p[w]=k;
            }
        }
    }
}
int main()
{
    int i,j,k,l1,l2,l3,l4,x,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d %d %d",&n,&m,&s,&x);
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
            if(i==j)
            {
                map[i][j].a=0;
                map[i][j].b=0;
            }
        else
            {
                map[i][j].a=INF;
                map[i][j].b=INF;
            }
        for(i=0;i<m;i++)
        {
            scanf("%d %d %d %d",&l1,&l2,&l3,&l4);
            map[l1][l2].a=l3;
            map[l2][l1].a=l3;
            map[l1][l2].b=l4;
            map[l2][l1].b=l4;
        }
        Dijkstra();
            printf("%d %d\n",d[x],d1[x]);
    }
}



解法三:(SPFA算法_bfs)

#include<stdio.h>
#include<string.h>
#include<queue>
#include<climits>
using namespace std;
long long INF=LONG_LONG_MAX;
long long dis[600],dis1[600];
int vis[600];
struct node
{
    int to;
    int w,w1;
};
int n,m,s,t,x;
vector<struct node>map[600];
void SPFA()
{
    queue<int>a;
    for(int i=0;i<n;i++)
    {
                dis[i]=INF;
                dis1[i]=INF;
    }
    memset(vis,0,sizeof(vis));
    dis[s]=0;
    dis1[s]=0;
    vis[s]=1;
    a.push(s);
    while(!a.empty())
    {
        int u=a.front();
        a.pop();
        vis[u]=0;
        int tt=map[u].size();
        for(int i=0;i<tt;i++)
        {
            int to=map[u][i].to;

                if(dis[u]<INF&&(dis[to]>dis[u]+map[u][i].w||(dis[to]==dis[u]+map[u][i].w)&&dis1[to]>dis1[u]+map[u][i].w))
                {
                    dis[to]=dis[u]+map[u][i].w;
                    dis1[to]=dis1[u]+map[u][i].w1;
                    if(!vis[to])
                    {
                        a.push(to);
                        vis[to]=1;
                    }
            }
        }
    }
}
int main()
{
    int T,u,v,w,w1;
    struct node temp;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d %d",&n,&m,&s,&t);
        for(int i=0;i<n;i++)
            map[i].clear();
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d %d %d",&u,&v,&w,&w1);
            temp.to=v;
            temp.w=w;
            temp.w1=w1;
            map[u].push_back(temp);
            temp.to=u;
            map[v].push_back(temp);
        }
            SPFA();
                printf("%lld %lld\n",dis[t],dis1[t]);
    }
}


解法四:(SPFA_dfs算法)

#include<stdio.h>
#include<string.h>
int INF=65535;
int d[600],d1[600];
int vis[600],head[600];
struct node
{
    int v;
    int w,w1;
    int next;
}st[100000];
int n,m,s,t,x,l;
void add(int u,int v,int w,int w1)
{
    st[l].v=v;
    st[l].w=w;
    st[l].w1=w1;
    st[l].next=head[u];
    head[u]=l++;
}
int spfa_dfs(int u)
{
    vis[u]=1;
    for(int k=head[u]; k!=-1; k=st[k].next)
    {
        int v=st[k].v,w=st[k].w,w1=st[k].w1;
        if( d[u]+w <d[v]||(d[u]+w ==d[v]&&d1[u]+w1 <d1[v] ))
        {
            d[v]=d[u]+w;
            d1[v]=d1[u]+w1;
            if(!vis[v])
            {
                if(spfa_dfs(v))
                    return 1;
            }
            else
                return 1;
        }
    }
    vis[u]=0;
    return 0;
}
int main()
{
    int T,u,v,w,w1,k,i;
    scanf("%d",&T);
    while(T--)
    {
        l=0;
        scanf("%d %d %d %d",&n,&m,&s,&t);
        for(i=0;i<=n;i++)
        {
            d[i]=INF;
            d1[i]=INF;
        }
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d %d %d",&u,&v,&w,&w1);
            add(u,v,w,w1);
            add(v,u,w,w1);
        }
        d[s]=0;
        d1[s]=0;
        k=spfa_dfs(s);
                printf("%d %d\n",d[t],d1[t]);
    }
}


解法五:(Bellman_Ford)

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
#define INF 0x7ffffff
struct node
{
    int to,cost,cost1;
}edge[2000];
int pre[600];
int dis[600],dis1[600];
int n,m,src;
int relax(int u,int v,int cost,int cost1)
{
    if(dis[v]>dis[u]+cost||(dis[v]==dis[u]+cost&&dis1[v]>dis1[u]+cost1))
    {
        dis[v]=dis[u]+cost;
        dis1[v]=dis1[u]+cost1;
        return 1;
    }
    else
        return 0;
}
int Bellman_Ford()
{
    int i,j,flag;
    for(i=1;i<=n;i++)
        {
            dis[i]=INF;
            dis1[i]=INF;
        }
        dis[i]=0;
            dis1[i]=0;
    for(i=1;i<n;i++)
        {
            flag=0;
            for(j=0;j<m;j++)
            {
                if(relax(j,edge[j].to,edge[j].cost,edge[j].cost1))
                {
                    pre[j]=edge[j].to;
                    flag=1;
                }
            }
            if(!flag)
                break;
        }
        for(i=0;i<m;i++)
        {
            if(relax(i,edge[i].to,edge[i].cost,edge[i].cost1))
                return 0;
        }
        return 1;
}
int main()
{
    int i,j,T,t,l1,l2,l3,l4;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d %d",&n,&m,&src,&t);
        for(i=0;i<m;i++)
        {
            scanf("%d %d %d %d",&l1,&l2,&l3,&l4);
            edge[l1].to=l2;
            edge[l1].cost=l3;
            edge[l1].cost1=l4;
            edge[l2].to=l1;
            edge[l2].cost=l3;
            edge[l2].cost1=l4;

        }
        Bellman_Ford();
        //if(Bellman_Ford())
            printf("%d %d\n",dis[t],dis1[t]);
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值