Description
原题略,就是给一个n个点m条边的有向图,如果
x
–>
Solution
由于这题范围比较小,可以考虑dfs+spfa,dfs+dijstra……
把原图分成2*lim+1层,其中最底层为原图,我们把它称为第0层,对于每个偶数层,对于一条边
(u,v)
,我们把
(u,v′)
连一条边,边权为
l
,其中
然后,我们就得到了一个有向图,对该图做各种最短路算法即可。
注意:加的边可能很多,注意最短路算法的复杂度。
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 20001
#define M 1000001
#define inf 2147483647
using namespace std;
int to[M],next[M],last[M],val[M],num=0;
int dis[M];
void link(int x,int y,int c)
{
num++;
to[num]=y;
next[num]=last[x];
last[x]=num;
val[num]=c;
}
int d[N],vis[N];
int maxlim;
void spfa()
{
memset(dis,60,sizeof(dis));
maxlim=dis[0];
dis[1]=0;
vis[1]=true;
d[1]=1;
int l=0,r=1;
while(l<r)
{
l++;
int x=d[l];
for(int i=last[x];i;i=next[i])
{
int v=to[i];
if(dis[x]+val[i]<dis[v])
{
dis[v]=dis[x]+val[i];
if(!vis[v])
{
vis[v]=true;
d[++r]=v;
}
}
}
vis[x]=false;
}
}
int main()
{
freopen("sigemago.in","r",stdin);
freopen("sigemago.out","w",stdout);
int n,m;
int l,lim;
cin>>n>>m>>l>>lim;
fo(i,1,m)
{
int x,y,c;
scanf("%d %d %d",&x,&y,&c);
for(int j=0;j<=lim*2;j+=2)
{
link(x+n*j,y+n*(j+1),l);
link(x+n*(j+1),y+n*(j+2),0);
link(x+j*n,y+j*n,c);
}
}
spfa();
int ans=inf;
for(int i=0;i<=lim*2;i+=2)
ans=min(ans,dis[n+n*i]);
if(ans>=maxlim) cout<<-1;
else cout<<ans;
}