1.三分+最短路
参考 苟且的狮子 博客

https://blog.nowcoder.net/n/1fb0276367aa44df861b17f185653058

#include<bits/stdc++.h>
#define ll long long

#define pr pair<ll,ll>

using namespace std;


const int N=2e5+10;
const ll inf=1e18;
struct node{
    int v,len,next;
}a[N*2];
int pre[N],cnt=0;
ll dis[N],vis[N];
ll k[N],b[N];
int n,m,h;

void add( int u,int v,int len )
{
//    a[cnt].v=v , a[cnt].len=len , a[cnt].next=pre[u];
    a[cnt]={ v,len,pre[u] };
    pre[u]=cnt++;
}

void init()
{
    memset(pre,-1,sizeof(pre)),cnt=0;
}

ll check( ll x,int s=1 ) // 起点 
{ 
    memset( dis,0x3f,sizeof(dis) );
    memset( vis,0,sizeof(vis) );
    priority_queue<pr,vector<pr>,greater<pr> > q;
    q.push( make_pair(0,s) );
    dis[s]=0;
    while( q.size() ) 
    {
        int u=q.top().second;
        q.pop();
        vis[u]=1;
        for( int i=pre[u];~i;i=a[i].next )
        {
            int v=a[i].v,id=a[i].len;
            ll len=k[id]*x+b[id];

            if( !vis[v] && dis[v]>dis[u]+len )
            {
                dis[v]=dis[u]+len;
                q.push( make_pair(dis[v],v) );
            }
        }
    }
    return dis[n]; 
}



void solve()
{
    int l=0,r=h;
    ll ans=-1e18; 
    while( r-l>5 )
    {
        int mid1=l+(r-l)/3,mid2=r-(r-l)/3;
        ll ans1=check(mid1),ans2=check(mid2);
        if( ans1<ans2 ) l=mid1;
        else r=mid2;
    }
    for( int i=l;i<=r;i++ ) 
    {
        ans=max(ans,check(i));
    }

    printf("%lld\n",ans);
}


int main()
{
    scanf("%d%d%d",&n,&m,&h);

    init();
    int x,y,z;
    for( int i=1;i<=m;i++ )
    {
        scanf("%d%d%lld%lld",&x,&y,&k[i],&b[i]); 
        add(x,y,i);
//        add(y,x,i);
    }
    solve();

}