HDU 2066 一个人的旅行

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2066
题意:应该看懂了。。。
思路:就是简单的最短路径的模板,下面我用三种方法来做这道题。
(1)Floyd:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int Max=1001;
int map[Max][Max],endd[Max];
void floyd(int n)
{
    int i,j,k;
    for(i=0; i<=n; i++)
    {
        for(j=0; j<=n; j++)
        {
            if(map[j][i]!=INF)
            {
                for(k=0; k<=n; k++)
                {
                    if(map[j][i]+map[i][k]<map[j][k])
                    {
                        map[j][k]=map[j][i]+map[i][k];
                    }
                }
            }

        }
    }
}
int main()
{
    int T,S,D,temp=0,i,j;
    while(cin>>T>>S>>D)
    {
        memset(endd,0,sizeof(endd));
        memset(map,INF,sizeof(map));
        for(i=0; i<Max; i++)
        {
            map[i][i]=0;
        }
        int a,b,time,lj,xq;//lj表示临近城市,xq表示想去的城市。
        for(i=1; i<=T; i++)
        {
            cin>>a>>b>>time;
            if(temp<=max(a,b))
            {
                temp=max(a,b);//确定临界矩阵,防止超时。
            }
            if(time<map[a][b])
            {
                map[a][b]=map[b][a]=time;
            }
        }
        for(i=1; i<=S; i++)
        {
            cin>>lj;
            map[0][lj]=map[lj][0]=0;
        }
        for(i=1; i<=D; i++)
        {
            cin>>xq;
            endd[i]=xq;//想去的城市即终止点。
        }
        floyd(temp);
        int result=INF;
        for(i=1; i<=D; i++)
        {

            if(map[0][endd[i]]<result)
            {
                result=map[0][endd[i]];//从出发点到想去的城市的最短路就是所求的最短距离。
            }
        }
        printf("%d\n",result);
    }

    return 0;
}

(2)Dijkstar:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int Max=1001;
int map[Max][Max],vis[Max],dis[Max],endd[Max];
void Dijkstar(int n)
{
    int i,j,min;
    memset(vis,0,sizeof(vis));
    int pos=0;
    vis[pos]=1;
    dis[pos]=0;
    for(i=1; i<=n; i++)
    {
        dis[i]=map[pos][i];//对dis进行赋值。
    }
    for(i=0; i<n-1; i++)
    {
        min=INF;
        for(j=1; j<=n; j++)

        {
            if(vis[j]==0&&min>dis[j])
            {
                min=dis[j];
                pos=j;
            }
        }//找出此城市的最短路。
        if(min<INF)
            vis[pos]=1;
        else
        {
            break;
        }
        for(j=1; j<=n; j++)
        {
            if(vis[j]==0&&dis[j]>dis[pos]+map[pos][j])
            {
                dis[j]=dis[pos]+map[pos][j];//对dis进行更新,此时的dis和prim中的low不一样,prim中low表示的是从此城市到另外一个城市的最短路径,而这里的dis是指从出发点到此城市的最短路径。
            }
        }
    }
}
int main()//主函数和Dijkstar中的一样,只是求最短路的方法不一样了。
{
    int t,i,j,T,S,D;

    while(cin>>T>>S>>D)
    {
        int temp=0;
        memset(endd,0,sizeof(endd));
        for(i=0; i<Max; i++)
        {
            for(j=0; j<Max; j++)
            {
                if(i==j)
                    map[i][j]=0;
                else
                {
                    map[i][j]=INF;
                }
            }
        }
        int a,b,time,lj,xq;
        for(i=0; i<T; i++)
        {
            cin>>a>>b>>time;
            if(temp<max(a,b))
            {
                temp=max(a,b);
            }
            if(time<map[a][b])
            {
                map[a][b]=map[b][a]=time;
            }
        }
        for(i=0; i<S; i++)
        {
            cin>>lj;
            map[0][lj]=map[lj][0]=0;
        }
        for(i=0; i<D; i++)
        {
            cin>>xq;
            endd[i]=xq;
        }
        Dijkstar( temp);
        int result=INF;
        for(i=0; i<D; i++)
        {
            if(dis[endd[i]]<result)
            {
                result=dis[endd[i]];
            }
        }
        printf("%d\n",result);
    }
    return 0;
}

(3)spfa

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const int Max=1001;
int map[Max][Max],vis[Max],dis[Max],endd[Max],start[Max];
int S;
int temp;
void spfa()
{
    int i,j;
    queue<int>q;//定义一个对列q
    memset(vis,0,sizeof(vis));
    for(i=1;i<=temp;i++)
    {
        dis[i]=INF;//对dis赋值。
    }
     for(i=0;i<S;i++)
    {
        dis[start[i]]=0;
        q.push(start[i]);
        vis[start[i]]=1;
    }//将第一个城市入队
    while(!q.empty())//将剩余的城市依次入队
    {
        int ans=q.front();
        q.pop();
        vis[ans]=0;
        for(i=1;i<=temp;i++)
        {
            if(dis[i]>dis[ans]+map[ans][i])
            {
                dis[i]=dis[ans]+map[ans][i];
                if(vis[i]==0)
                {
                    q.push(i);
                    vis[i]=1;
                }
            }

        }

    }
}
int main()//与前面的方法雷同
{
    int t,i,j,T,D;
    while(cin>>T>>S>>D)
    {
        temp=0;
        memset(endd,0,sizeof(endd));
        for(i=0; i<Max; i++)
        {
            for(j=0; j<Max; j++)
            {
                if(i==j)
                    map[i][j]=0;
                else
                {
                    map[i][j]=INF;
                }
            }
        }
        int a,b,time,lj,xq;
        for(i=0; i<T; i++)
        {
            cin>>a>>b>>time;
            if(temp<max(a,b))
            {
                temp=max(a,b);
            }
            if(time<map[a][b])
            {
                map[a][b]=map[b][a]=time;
            }
        }
        for(i=0; i<S; i++)
        {
            cin>>lj;
            start[i]=lj;
        }
        for(i=0; i<D; i++)
        {
            cin>>xq;
            endd[i]=xq;
        }
        spfa();
        int result=INF;
        for(i=0; i<D; i++)
        {
            if(dis[endd[i]]<result)
            {
                result=dis[endd[i]];
            }
        }
        printf("%d\n",result);
    }
    return 0;
}

基本上这三个方法就是最短路径的模板。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值