最短路变短了 (思维+反向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;
 } 

原文地址:https://www.cnblogs.com/Accepting/p/12678654.html

时间: 2024-10-16 13:31:19

最短路变短了 (思维+反向djstrea)的相关文章

81进制,用多进制方式把一个长长的整数变短

最近在做项目有些资源要用到唯一的标识code,这个code要全局唯一,因此比较长,有25位,long只能处理到19位.另外25位长的一个整数阅读显示都不是很理想,因此开发了一个多进制的转换类.思想接近把一个域名用几个字符代替.下面就是实现的具体java代码,目前支持到81进制. 1 import java.math.BigInteger; 2 import java.util.Arrays; 3 import java.util.Date; 4 5 /** 6 * 7 * @author 程序员

SSH 登录忽然变慢 与DNS反向解析

环境描述: 1.      操作系统:CentOS6,CentOS7,Ubuntu 2.      DNS:202.106.0.20[北京联通],202.106.196.115[北京联通],114.114.114.114[114DNS] 陆续收到研发.测试部门反馈,内网SSH登录忽然变慢了,会卡在登录界面很久: 紧接着又收到反馈,MySQL使用客户端连接不上,或者连接很慢: 再接着,程序连接zookeepr&kafka超时情况时有发生: 很明显的DNS解析问题,SSH 可以在配置文件/etc/s

Ubuntu12.04中如何让命令行路径变短

Ubuntu12.04中命令行路径随着不断的深入文件夹而变长,非常的烦人.在CentOS6.5中却没有这样的烦恼.这是为什么呢? 我查看了下CentOS6.5的bash配置,发现不同的地方: PS1="[\[email protected]\h \W]\\$ " 接着我便在Ubuntu12.04中修改试试: $ vi ~/.bashrc 改成上图所示,保存.注销,登入,哈哈,有效果啦:

android textview 设置单行最大宽度和ellipsize省略号时整体变短的问题

在 android 的textview中 同时设置 android:maxWidth="155dp"android:lines="1"android:ellipsize="end" 在部分手机上运行时,当textview的长度超过155dp时,会发现最后显示出来的长度并没有达到155dp,甚至还差的很宽,如图 解决方法: 把 android:lines="1" 替换为 android:singleLine="true

SP338ROADS题解--最短路变式

题目链接 https://www.luogu.org/problemnew/show/SP338 分析 联想到不久前做过的一道题\(Full\) \(Tank\),感觉可以用优先队列做,于是写了\(dijsktra\)(非负权图不敢用\(SPFA\)了) 然后发现错了,想了挺久,发现它实际上是可以找\(dis\)更大的走以花费更少的钱,于是把\(vis\)数组和\(dis\)数组全去掉就A了 优先队列保证取出的距离是最短的,如果距离相同,那么钱数是最小的,所以第一次取出\(n\)时就是答案,跑得

luogu 4366 [Code+#4]最短路 Dijkstra + 位运算 + 思维

Code: #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #define N 100004 #define M 4000000 #define inf 10000000000000 #define ll long long #define setIO(s) freopen(s".in","r",stdin) usin

[最短路,floyd] Codeforces 1204C Anna, Svyatoslav and Maps

题目:http://codeforces.com/contest/1204/problem/C C. Anna, Svyatoslav and Maps time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The main characters have been omitted to be short. You are give

(好题)2017-2018 ACM-ICPC, Asia Tsukuba Regional Contest F Pizza Delivery

题意:给n个点m条边的有向图.每次使一条边反向,问你1到2的最短路变短,变长,还是不变. 解法:遇到这种题容易想到正向求一遍最短路d1,反向再求一遍最短路d2.纪录原图上的最短路为ans,然后分开考虑各种情况. 变短的情况:d1[y[i]]+d2[x[i]]+z[i]<ans 否则就剩下不变和变长两种情况:那么如果边(x,y)是起点到终点的最短路必须边的话,就会变长,否则会不变. 接下来的问题是  怎么求最短路的必经边? 求出原图1到2最短路图(这里要和求单源点的最短路图区别开来,单源点的最短路

FLOyd算法 求任意最短路

此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在"Communications of the ACM"上.同年Stephen Warshall(史蒂芬·沃舍尔)也独立发表了这个算法.Robert W.Floyd这个牛人是朵奇葩,他原本在芝加哥大学读的文学,但是因为当时美国经济不太景气,找工作比较困难,无奈之下到西屋电气公司当了一名计算机操作员,在IBM650机房值夜班,并由此开始了他的计算机生涯. 作者:ahalei来源:51CTO博客|2014-03-26