[复习]Dijkstra+堆/SPFA/Dijkstra+优先队列 浣花溪公园

题目背景
最短路模板题目。SPFA 或 用堆优化的迪杰斯特拉算法均可实现。

题目描述
成都浣花溪公园是一座有着诗歌文化气息的公园,它以杜甫草堂的历史文化内涵为背景,运用现代园林和建筑设计的前沿理论,以自然雅致的景观和建筑凸现川西文化醇厚的历史底蕴,是一座集将自然景观和城市景观、古典园林和现代建筑艺术有机结合的城市公园。

周末,Mr.Zeng和他儿子在浣花溪公园“诗歌大道”上欣赏诗歌,刚诗兴正浓,Mr.Zeng忽然想起汽车的车门没锁,于是他们要在最快的时间内走出公园赶到公园门口停车场。我们把公园的景点用数字标号(从1 到 N-1),在两个景点中之间会有道路连接,并且Mr.Zeng和他儿子都是素质很高的人,他们不会穿越公园的草坪,只会沿着公园的小路行走。Mr.Zeng想知道从他们当前所处的位置 S 到公园的出口(标号固定为 N)所需要的最短时间。你能帮帮他吗?

输入格式
输入文件的第一行有3 个正整数:N、K、T 并且用空格隔开,分别表示公园景点数目、公园小路条数,以及他们当前所处的景点编号。
接下来 K 行,每行三个整数,表示小路连接的两个景点的编号以及走过这条小路所需要的时间。

输出格式
一个整数,表示他们走出公园所需要的最短时间。

样例数据
输入
3 2 1
1 2 3
2 3 4
输出
7

备注
【数据范围】
对于 60% 的数据,保证 N<=1000,K<=10000。
对于 100% 的数据,保证 N<=10000,K<=100000。
对于 100% 的数据,保证结果在 231 内。

分析: Dijkstra+堆/SPFA/Dijkstra+优先队列模板

代码:
Dijkstra+堆(多半是废了)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;

int getint() 
{
    int i = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-') f = -1; ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        i = (i << 3) + (i << 1) + ch - '0'; ch = getchar();
    }
    return i * f;
}

struct node
         {
            int w;
            int num;
         };

int n,k,x,y,i,j,tot,cnt,z,p,t;
int nxt[200100],w[200100],v[200100];
int pl[10010],first[10010];    
int dis[10010];                   
node heap[10010]; 

void add(int x,int y,int z)
{
    tot++;
    nxt[tot]=first[x];
    first[x]=tot;
    v[tot]=y;
    w[tot]=z;
}

void up(int x)
{
    int j;
    j=x>>1;
    while(j!=0&&heap[x].w<heap[j].w)
    {
        swap(heap[x],heap[j]);
        pl[heap[x].num]=x;
        pl[heap[j].num]=j;
        x=j;
        j=j>>1;
    }
}

void down(int x)
{
    int j;
    j=x<<1;
    while(j<=cnt)
    {
        if(j<cnt&&heap[j].w>heap[j+1].w)
            j++;
        if(heap[x].w<heap[j].w)
            break;
        else
        {
            swap(heap[x],heap[j]);
            pl[heap[x].num]=x;
            pl[heap[j].num]=j;
            x=j;
            j=j<<1;
        }
    }
}

int main()
{
    freopen("hhxgy.in","r",stdin);
    freopen("hhxgy.out","w",stdout);

    n=getint();k=getint();t=getint();
    for(int i=1;i<=k;++i)
    {
        x=getint();y=getint();z=getint();
        add(x,y,z);
        add(y,x,z);
    }

    memset(dis,127,sizeof(dis));
    dis[t]=0;

    for(int i=1;i<=n;++i)
    {
        heap[i].w=1E+9;
        heap[i].num=i;
        pl[i]=i;
    }

    cnt=n;
    heap[pl[t]].w=0;
    up(pl[t]);

    for(int i=1;i<=n;++i)
    {
        j=heap[1].num;
        heap[1]=heap[cnt];
        cnt--;
        down(1);
        p=first[j];
        while(p>0)
        {
            if(dis[j]+w[p]<dis[v[p]])
            {
                dis[v[p]]=dis[j]+w[p];
                heap[pl[v[p]]].w=dis[v[p]];
                up(pl[v[p]]);
            }
            p=nxt[p];
        }
    }

    cout<<dis[n]<<endl;
    return 0;
}

SPFA

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;

int getint()
{
    int sum=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
    if(ch=='-')
    {
        f=-1;
        ch=getchar();
    }
    for(;isdigit(ch);ch=getchar())
        sum=(sum<<3)+(sum<<1)+ch-48;
    return sum*f;
}

const int maxn=10010;
const int maxk=100010;
int n,k,t,x,y,z;
int tot,first[maxn],nxt[maxk*2],to[maxk*2],w[maxk*2];//双向边注意数组大小*2
int dis[maxn];
bool visit[maxn];
queue<int> que;

void addedge(int x,int y,int z)
{
    tot++;
    nxt[tot]=first[x];
    first[x]=tot;
    to[tot]=y;
    w[tot]=z;
    tot++;
    nxt[tot]=first[y];
    first[y]=tot;
    to[tot]=x;
    w[tot]=z;
}

void SPFA()
{
    memset(dis,0x3f3f3f3f,sizeof(dis));//记得给dis赋一个极大初值(但是不要用127,因为dis[u]+w[p]的时候可能会爆int)
    dis[t]=0;
    que.push(t);
    visit[t]=true;
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        visit[u]=false;//记得出栈
        for(int p=first[u];p;p=nxt[p])
        {
            int v=to[p];
            if(dis[v]>dis[u]+w[p])
            {
                dis[v]=dis[u]+w[p];
                if(!visit[v])//记得判断v是否在栈中
                    que.push(v); 
            }
        }   
    }
}

int main()
{
    freopen("park.in","r",stdin);
    freopen("park.out","w",stdout);

    n=getint(),k=getint(),t=getint();
    for(int i=1;i<=k;++i)
    {
        x=getint(),y=getint(),z=getint();
        addedge(x,y,z);
    }

    SPFA();

    cout<<dis[n]<<'\n';
    return 0;
}

Dijkstra+优先队列

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;

int getint()
{
    int sum=0,f=1;
    char ch;
    for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
    if(ch=='-')
    {
        f=-1;
        ch=getchar();
    }
    for(;isdigit(ch);ch=getchar())
        sum=(sum<<3)+(sum<<1)+ch-48;
    return sum*f;
}

const int maxn=10010;
const int maxk=100010;
int n,k,t,x,y,z;
int tot,first[maxn],nxt[maxk*2],to[maxk*2],w[maxk*2];//双向边注意数组大小*2
int dis[maxn];
priority_queue<pair<int,int> > que;

void addedge(int x,int y,int z)
{
    tot++;
    nxt[tot]=first[x];
    first[x]=tot;
    to[tot]=y;
    w[tot]=z;
    tot++;
    nxt[tot]=first[y];
    first[y]=tot;
    to[tot]=x;
    w[tot]=z;
}

void dijkstra()
{
    memset(dis,0x3f3f3f3f,sizeof(dis));//记得给dis赋一个极大初值(但是不要用127,因为dis[u]+w[p]的时候可能会爆int)
    dis[t]=0;
    que.push(make_pair(0,t));
    while(!que.empty())
    {
        int u=que.top().second;//普通队列是que.front(),优先队列是que.top()
        que.pop();
        for(int p=first[u];p;p=nxt[p])
        {
            int v=to[p];
            if(dis[v]>dis[u]+w[p])
            {
                dis[v]=dis[u]+w[p];
                que.push(make_pair(-dis[v],v));//优先队列是从大到小排,所以用负dis可实现从小到大排;而且dijkstra是直接入栈,不需要判断有没有在栈中
            }
        }
    }
}

int main()
{
    freopen("park.in","r",stdin);
    freopen("park.out","w",stdout);

    n=getint(),k=getint(),t=getint();
    for(int i=1;i<=k;++i)
    {
        x=getint(),y=getint(),z=getint();
        addedge(x,y,z);
    }

    dijkstra();

    cout<<dis[n]<<'\n';
    return 0;
}

本题结。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值