ACM-ICPC 2018 南京赛区网络预赛丨Magical Girl Haze丨dijkstra丨分层图做法

题意:n个点,m条带权有向边,k次免费通行的机会,求最短路。
思路:有dp的方法和简单的分层最短路做法,分层的思路如下:把每个点都拆成k+1个分点,把图变成k+1个层次,每个层次的点除了连着同层的下一个点之外,还有一条免费边连着下一层对应的点。因为层数限制为k+1,也就是路径最多k次穿越不同层次,也就满足题目k次免费的情景。在这个图的基础上做一次最短路就能得到答案了,时间复杂度用dijkstra是OK的。
下面是一个简单的例子(k=2):
这里写图片描述

后来我发觉这个图其实还是有点粗糙, 严格地来说,1号位置只需要一个点就够了,这是因为我们希望走0边的机会尽量多。为了建图方便,所以代码里是都拆了一样多的点。然后最后答案也不用去额外连一个end节点去求,已经知道终点了,只要终点的每一层都遍历一次即可。
还有个很奇怪的地方是数据范围,似乎要比预期得还要大许多。


#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1500005;
const int M=3000500;
const ll INF=0x7f7f7f7f;
int n,m,k,T;
int head[N],ent;
struct Edge{
    int v,nx,w;
}ed[M<<1];

void AddEd(int u,int v,int w)
{
    ed[++ent]={v,head[u],w};
    head[u]=ent;
}

struct Qnode{
    int n; ll d;
    friend bool operator < (Qnode a,Qnode b)
    {return a.d>b.d;}
};
ll dist[N];

void Dijkstra(int u)
{
    priority_queue<Qnode> q;
    dist[u]=0;
    q.push({u,0});
    while(!q.empty()){
        Qnode p=q.top();
        q.pop();
        u=p.n;
        for(int i=head[u],v;~i;i=ed[i].nx){
            v=ed[i].v;
            if(dist[v]>dist[u]+ed[i].w){
                dist[v]=dist[u]+ed[i].w;
                q.push({v,dist[v]});
            }
        }
    }
}


int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&k);
        memset(head,-1,sizeof head);
        memset(dist,INF,sizeof dist);

        for(int i=1,u,v,w;i<=m;i++){
            scanf("%d%d%d",&u,&v,&w);
            for(int j=0;j<=k;j++){
                AddEd(u+j*n,v+j*n,w);
                if(j<k)
                AddEd(u+j*n,v+j*n+n,0);
            }
        }
        Dijkstra(1);

        ll ans=INF;
        for(int i=0;i<=k;i++)
            ans=min(ans,dist[n+n*k]);
        printf("%lld\n",ans);

        ent=0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值