GDOI 2016 Day2 T1 SigemaGO

Description

给出一张n个点,m条边的有向图。若A->B有一条边,B->C有一条边,则可以使用L的时间直接从A到C。总共只可以走lim次这样的近路。求1到n的最短路。若无解,输出-1。
n<=10000,m<=50000,lim<=5

Solution

加了一点点东西的最短路。
迪杰斯特拉有点麻烦,就直接打玄学算法sp(b)fa。
多开一维j,维护1到当前这个点走了j次近路的最短路。
出题人良心没有卡O(∩_∩)O

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a) for(int i=last[a];i;i=next[i])
#define N 10005
#define M 50005
using namespace std;
int n,m,l,x,y,z,L,lim,dis[N][6],d[M*5];
int last[N],next[M],t[M],v[M];
bool bz[N];
void add(int x,int y,int z) {
    t[++l]=y;v[l]=z;next[l]=last[x];last[x]=l;
}
int main() {
    freopen("sigemago.in","r",stdin);
    freopen("sigemago.out","w",stdout);
    scanf("%d%d%d%d",&n,&m,&L,&lim);
    fo(i,1,m) scanf("%d%d%d",&x,&y,&z),add(x,y,z);
    memset(dis,127,sizeof(dis));int mx=dis[0][0];fo(i,0,lim) dis[1][i]=0;
    int i=0,j=1;d[1]=1;bz[1]=1;
    while (i<j) {
        rep(k,d[++i]) 
            fo(l,0,lim) {
                if (dis[t[k]][l]>dis[d[i]][l]+v[k]) {
                    dis[t[k]][l]=dis[d[i]][l]+v[k];
                    if (!bz[t[k]]) bz[t[k]]=1,d[++j]=t[k];
                }
                if (l==lim) continue;
                rep(p,t[k]) if (dis[t[p]][l+1]>dis[d[i]][l]+L) {
                    dis[t[p]][l+1]=dis[d[i]][l]+L;
                    if (!bz[t[p]]) bz[t[p]]=1,d[++j]=t[p];
                }
            }
        bz[d[i]]=0;
    }
    if (dis[n][lim]!=mx) printf("%d",dis[n][lim]);
    else printf("-1");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值