JDOJ-1972: [JLOI2011]飞行路线

[文章目录]

Description

Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司。该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一定的价格。Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机。航空公司对他们这次旅行也推出优惠,他们可以免费在最多k种航线上搭乘飞机。那么Alice和Bob这次出行最少花费多少?

裸的分层图,用spfa搞定

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
int n,m,k,start,fna,ans;
int head[11000],to[101000],nxt[101000],data[101000],cnt;
struct node
{int d,u;};

int f[11000][20];
bool v[11000][20];
void add(int x,int y,int z)
{
    to[++cnt]=y;
    nxt[cnt]=head[x];
    head[x]=cnt;
    data[cnt]=z;
}
struct cmp
{
    bool operator() (const node x,const node y)
    {
        return f[x.d][x.u]>f[y.d][y.u];
    }
};
priority_queue <node,vector <node> ,cmp > q;
void spfa()
{
    memset(f,0x3f,sizeof(f));
    f[start][0]=0;
    node x;
    x.d=start;
    x.u=0;
    q.push(x);v[start][0]=1;
    while(!q.empty())
    {
        x=q.top();
        int use=x.u;
        q.pop();v[x.d][x.u]=0;
        for(int y,i=head[x.d];i;i=nxt[i])
        {
            if(f[y=to[i]][use]>f[x.d][use]+data[i])
            {
                f[y][use]=f[x.d][use]+data[i];
                if(!v[y][use])
                {
                    v[y][use]=1;
                    node tmp;
                    tmp.d=y,tmp.u=use;
                    q.push(tmp);
                }
            }
        }
        if(use==k) continue;
        for(int y,i=head[x.d];i;i=nxt[i])
        {
            if(f[y=to[i]][use+1]>f[x.d][use])
            {
                f[y][use+1]=f[x.d][use];
                if(!v[y][use+1])
                {
                    v[y][use+1]=1;
                    node tmp;
                    tmp.d=y,tmp.u=use+1;
                    q.push(tmp);
                }
            }
        }
    }
}
int read()
{
    int sum=0;
    char c;
    c=getchar();
    while(c==' '||c=='\n')
        c=getchar();
    while(c<='9'&&c>='0')
        sum=(sum<<3)+(sum<<1)+(c-'0'),c=getchar();
    return sum;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    scanf("%d%d",&start,&fna);
    for(int x,y,z,i=1;i<=m;i++)
    {
        x=read();
        y=read();
        z=read();
        add(x,y,z);
        add(y,x,z);
    }
    spfa();
    ans=1<<30;
    for(int i=0;i<=k;i++)
        ans=min(ans,f[fna][i]);
    printf("%d",ans);
    return 0;
}

头一道写读入优化的题

发表评论

邮箱地址不会被公开。 必填项已用*标注