CCPC 2018南京网络赛 Magical Girl Haze 优先队列+最短路

本文介绍了CCPC 2018南京网络赛中的一道题目,内容涉及优先队列和最短路算法。Haze是一位居住在1号城市的魔法少女,她需要通过不超过K条道路将距离变为0,以到达N号城市。题目要求计算最小的总距离。给出了三种解题思路:第一种利用优先队列和最短路,第二种是第一种方法的简单解释,第三种方法是分层图,但存在超时问题。
摘要由CSDN通过智能技术生成

There are NNN cities in the country, and MMM directional roads from uuu to v(1≤u,v≤n)v(1\le u, v\le n)v(1≤u,v≤n). Every road has a distance cic_ici​. Haze is a Magical Girl that lives in City 111, she can choose no more than KKK roads and make their distances become 000. Now she wants to go to City NNN, please help her calculate the minimum distance.

Input

The first line has one integer T(1≤T≤5)T(1 \le T\le 5)T(1≤T≤5), then following TTT cases.

For each test case, the first line has three integers N,MN, MN,M and KKK.

Then the following MMM lines each line has three integers, describe a road, Ui,Vi,CiU_i, V_i, C_iUi​,Vi​,Ci​. There might be multiple edges between uuu and vvv.

It is guaranteed that N≤100000,M≤200000,K≤10N \le 100000, M \le 200000, K \le 10N≤100000,M≤200000,K≤10,
0≤Ci≤1e90 \le C_i \le 1e90≤Ci​≤1e9. There is at least one path between City 111 and City NNN.

Output

For each test case, print the minimum distance.

样例输入复制

1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2

样例输出复制

3

题目来源

ACM-ICPC 2018 南京赛区网络预赛

 

第一种解法:使用优先队列+最短路

#include<bits/stdc++.h>
using namespace std;

#define maxn 100007
vector<pair<long long,long long>>maps[maxn];
long long d[maxn][13];
int n,m,k;

void spfa(int x)
{
    queue<int>q;
    int n1,n2;
    n1=1;
    q.push(n1);
    while(!q.empty())
    {
        n1=q.front();
        q.pop();
        for(int i=0;i<maps[n1].size();++i)
        {
            n2=maps[n1][i].first;
            long long w=maps[n1][i].second;
            if(x==0)
            {
                if(d[n2][x]>d[n1][x]+w)
                {
                    d[n2][x]=d[n1][x]+w;
                    q.push(n2);
                }
            }
            else
            {
                if(d[n2][x]>d[n1][x]+w||d[n2][x]>d[n1][x-1])
                {
                    d[n2][x]=min(d[n1][x]+w,d[n1][x-1]);
                    q.push(n2);
                }
            }
        }
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {

        cin>>n>>m>>k;
        for(int i=1;i<=n;++i)
        {
            for(int j=0;j<=k;++j)
                d[i][j]=0x3f3f3f3f;
        }
        for(int i=0;i<=n;++i)
            maps[i].clear();
        for(int i=1;i<=m;++i)
        {
            int x,y,z;
            cin>>x>>y>>z;
            maps[x].push_back(make_pair(y,z));
        }
        memset(d[1],0,sizeof(d[1]));
        for(int i=0;i<=k;++i)
            spfa(i);

        cout<<d[n][k]<<endl;

    }
    return 0;
}

 

第二种解法:第一种解法的傻逼翻译版,k遍最短路

#include<bits/stdc++.h>
using namespace std;

#define maxn 100007
long long dis[maxn][11];
int done[maxn][11];
vector<pair<int,int>>maps[maxn];
struct  node
{
    int u;
    int d;
    int f;
    node(int a=0,int b=0,int c=0) :u(a),d(b),f(c){}

    friend bool operator<(const node &a,const node &b)
    {
        return a.d>b.d;
    }
};
int n,m,k;

void spfa()
{
    node n1(1,0,0),n2;
    priority_queue<node>pq;
    pq.push(n1);
    int u,d,f;
    while(!pq.empty())
    {
        n1=pq.top();
        pq.pop();
        u=n1.u;
        d=n1.d;
        f=n1.f;
        if(done[u][f]) continue;
        done[u][f]=1;

        for(int i=0;i<maps[u].size();++i)
        {
            int v=maps[u][i].first;
            int w=maps[u][i].second;
            if(f<k&&!done[v][f+1]&&dis[v][f+1]>dis[u][f])
            {
                n2.d=d;
                n2.f=f+1;
                n2.u=v;
                pq.push(n2);
                dis[v][f+1]=dis[u][f];
            }
            if(!done[v][f]&&dis[v][f]>dis[u][f]+w)
            {
                dis[v][f]=dis[u][f]+w;
                n2.d=d+w;
                n2.f=f;
                n2.u=v;
                pq.push(n2);
            }
        }
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>k;

        for(int i=0;i<=n;++i)
            maps[i].clear();
        for(int i=1;i<=n;++i)
        {
            for(int j=0;j<=k;++j)
            {
                dis[i][j]=0x3f3f3f3f;
                done[i][j]=0;
            }
        }
        for(int i=1;i<=m;++i)
        {
            int a,b,c;
            cin>>a>>b>>c;
            maps[a].push_back(make_pair(b,c));
        }
        dis[1][0]=0;
        spfa();
        cout<<dis[n][k]<<endl;
    }

    return 0;
}

 

第三种解法:分层图,但莫名超时,求解[

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值