Topics

\(solution:\)

Speaking about the nature of the shortest path, it can solve the problem of finding the shortest path. But such a problem can only be guaranteed to have either of the following two properties:

  1. The upper boundaries of the path I have traveled will not change!

  2. The length of the path must vary monotonously after I walk through a certain side (only increasing or decreasing). Just think about the principle of $dij $.

This problem satisfies the second condition. When we go through a certain side and back path, the weight will decrease, so we can use the shortest path. Then we may not know the initial weights, which can be dichotomized, but it adds complexity. We can consider running the shortest path backward (this is a common routine), but we need to solve an equation with the whole up in the middle. This solution can be divided into two parts, but it will also increase the complexity. In the exam room, we can imitate the whole situation and change it correctly. (That's what bloggers do with QAQ)

Then just look at the code.

\(code:\)

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define rg register int

using namespace std;

int n,m,k;
int s,t,w;
int top,ans;
bool a[500005];
int d[500005];
int fa[500005];
bool vis[500005];

struct su{
    int to,next;
}b[2000005];
int tou[500005];

struct pi{
    int da,id;
    inline bool operator <(const pi &x)const{
        if(da==x.da)return id>x.id;
        return da>x.da;
    }
};
priority_queue<pi> q;

inline int qr(){
    register char ch; register bool sign=0; rg res=0;
    while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    if(sign)return -res; else return res;
}

inline int get(int x){ //Solve the upward integral equation
    ll z=(ll)x*k;
    if(z%(k-1)==0)z=z/(k-1);
    else z=z/(k-1)+1;
    return z;
}

inline void solve(){ //Reverse shortest path
    for(rg i=1;i<=n;++i) d[i]=2e9;
    d[t]=w; q.push(pi{0,t});
    while(!q.empty()){
        rg i=q.top().id; q.pop();
        if(i==s)return ; //Eureka
        if(vis[i])continue; //Visited
        for(rg j=tou[i];j;j=b[j].next){
            rg to=b[j].to;
            if(vis[to])continue;
            rg v=1+d[i]; if(!a[i]) v=get(d[i]); //Find the Real Distance
            if(v<d[to])d[to]=v,fa[to]=i,q.push(pi{v,to});
            // Update the distance, record the precursor for easy output, add to the queue
        }
    }
}

int main(){
    n=qr(); m=qr(); k=qr();
    for(rg i=1;i<=n;++i) a[i]=qr();
    for(rg i=1;i<=m;++i){
          rg x=qr(),y=qr();
          b[++top]=su{y,tou[x]}; tou[x]=top;
          b[++top]=su{x,tou[y]}; tou[y]=top;
    }
    s=qr(); t=qr(); w=qr();
    solve(); printf("%d\n",d[s]);
    printf("%d",s);
    for(rg i=fa[s];i;i=fa[i])
        printf("->%d",i);
    puts("");
    return 0;
}