zoukankan      html  css  js  c++  java
  • 最短路变短了 (思维+反向djstrea)

    题解:设有一条边x->y,数组dis1[i]表示从1到i的最短距离,dis2[i]表示从n到i的最短距离。

    1 如果说将x->y反向之前没有经过x->y,但是反向后我经过了x,y说明找到了一个更优的路径,那么反向后的答案就是dis1[y]+dis2[x]+(x,y),如果说反向后我没有经过

    x->y,那也就是说x->y正向反向对dis[n]的结果没有影响喽。

    2 如果说反向之前我经过了x->y,如果反向后没有经过x->y,那么此时的最短路也一定是大于等于dis1[n]的,因为会有一条新的路径长度处于dis1[n]和dis1[y]+dis2[x]+(x,y)之间。如果反向后经过了x->y,那么反向后的答案就是dis1[y]+dis2[x]+(x,y)。

    综上所述,我们只需要判断dis1[y]+dis2[x]+(x,y)和dis1[n]的关系就行了。(看起来有点绕,仔细品品还是很有意思的)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll N=2e5+7;
    const ll INF=1e18+7;
    
    struct stu{
        ll a,b;
        bool friend operator<(const stu &x,const stu &y){
            return x.b>y.b;
        }
    };
    vector<stu>ve1[N];
    vector<stu>ve2[N];
    ll l[N],r[N],w[N];
    ll n,m;
    bool mark[N];
    ll dis1[N],dis2[N];
    void add1(ll x,ll y,ll weight){
        ve1[x].push_back({y,weight});
    }
    void add2(ll x,ll y,ll weight){
        ve2[x].push_back({y,weight});
    }
    void inll(){
        for(ll i=1;i<=n;i++){
            dis1[i]=dis2[i]=INF;
        }
    }
    void djstrea1(ll s){  
        priority_queue<stu>que;
        dis1[s]=0;  
        que.push({s,0});  
        while(que.size()){  
           stu xx=que.top();  
           que.pop();
           if(mark[xx.a]==1) continue ;  
           mark[xx.a]=1;  
           for(ll i=0;i<ve1[xx.a].size();i++){  
               ll dx=ve1[xx.a][i].a;  
               ll dy=ve1[xx.a][i].b; 
               if(mark[dx]==0&&dis1[dx]>dis1[xx.a]+dy){  
                   dis1[dx]=dis1[xx.a]+dy; 
                   que.push({dx,dis1[dx]});  
                 }  
             }  
           }  
    }
    void djstrea2(ll s){  
        priority_queue<stu>que;
        dis2[s]=0;  
        que.push({s,0});  
        while(que.size()){  
           stu xx=que.top();  
           que.pop();
           if(mark[xx.a]==1) continue ;  
           mark[xx.a]=1;  
           for(ll i=0;i<ve2[xx.a].size();i++){  
               ll dx=ve2[xx.a][i].a;  
               ll dy=ve2[xx.a][i].b;  
               if(mark[dx]==0&&dis2[dx]>dis2[xx.a]+dy){  
                   dis2[dx]=dis2[xx.a]+dy; 
                   que.push({dx,dis2[dx]});  
                 }  
             }  
           }  
    }
    int main(){
        cin>>n>>m;
        inll(); 
        for(ll i=1;i<=m;i++){
            ll x,y,z;
            cin>>x>>y>>z;
            l[i]=x;r[i]=y;w[i]=z;
            add1(x,y,z);
            add2(y,x,z);
        }
        djstrea1(1); 
        memset(mark,0,sizeof mark);
        djstrea2(n);
        ll t;
        cin>>t;
        while(t--){
            ll i;cin>>i;
            cout<<(dis1[n]>dis1[r[i]]+dis2[l[i]]+w[i]? "YES":"NO")<<endl;
        }
        return 0;
     } 
  • 相关阅读:
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业01
    学期总结
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言I博客作业04
    C语言I博客作业03
  • 原文地址:https://www.cnblogs.com/Accepting/p/12678654.html
Copyright © 2011-2022 走看看