链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题号:NC202496
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
给定一个有向带权图,其中包括 n个城市,城市编号从1 到n,有向边的编号从 1 到 m,现在有一个人位于城市 1,并且想要到城市n旅游。现在政府正在决定将一条道路反向,这个人想知道在某一指定道路反向的情况到达城市n最短路径长度会不会变短。
保证开始给定的图从城市1可以到达城市n,若边反向后城市1不能到达城市n,我们视为最短路径长度没有变短。
输入描述:
第一行包括两个整数n,m(1≤n≤100000,1≤m≤200000)
接下来m行每行三个整数u,v,c (1≤u,v≤n, 1≤c≤10^9),分别代表一条有向边的起点,终点和边权。保证没有自环。
接下来一行一个整数q(1≤q≤200000),代表查询组数,查询之间是独立的。
接下来q行每行一个整数x(1≤x≤m),代表询问将第x条边反向后到达城市n的最短路长度会不会变短。
输出描述:
共q行,如果最短路变短输出YES,否则输出NO。
示例1
输入
3 4 1 2 100 2 3 100 3 1 100 2 1 1 2 1 4
输出
NO YES
说明
第一条边反向后从点1无法到达点3,所以输出NO。
第四条边反向后从点1到点3的最短路长度从200减少到101,所以输出YES
分析
代码实现
#include<bits/stdc++.h>
using namespace std;
long long n,m,u,v,c,q,x;
long long cnt[200009],sum;
long long dist[200009],path[200009],g[200009],l,r;
bool flag[100009];
struct Node{
long long id;
long long dist;
Node(){
}
Node(long long i,long long d){
id=i;
dist=d;
}
friend bool operator <(Node a,Node b){
return a.dist>b.dist;
}
};
struct inf{
long long x;
long long y;
long long w;
};
inf edg[200009];
vector<Node>vt[200009],vt2[200009];
void Dijkstra2(int sid){
priority_queue<Node>pque;
memset(flag,false,sizeof(flag));
memset(dist,0x3f,sizeof(dist));
dist[sid]=0;
pque.push(Node(sid,dist[sid]));
while(pque.size()){
Node from=pque.top();
pque.pop();
if(flag[from.id]){
continue;
}
flag[from.id]=true;
for(auto to:vt2[from.id]){
if(!flag[to.id]&&dist[to.id]>dist[from.id]+to.dist){
dist[to.id]=dist[from.id]+to.dist;
pque.push(Node(to.id,dist[to.id]));
}
}
}
}
void Dijkstra(int sid){
priority_queue<Node>pque;
memset(flag,false,sizeof(flag));
memset(dist,0x3f,sizeof(dist));
dist[sid]=0;
pque.push(Node(sid,dist[sid]));
while(pque.size()){
Node from=pque.top();
pque.pop();
if(flag[from.id]){
continue;
}
flag[from.id]=true;
for(auto to:vt[from.id]){
if(!flag[to.id]&&dist[to.id]>dist[from.id]+to.dist){
dist[to.id]=dist[from.id]+to.dist;
pque.push(Node(to.id,dist[to.id]));
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&c);;
vt[u].push_back(Node(v,c));
vt2[v].push_back(Node(u,c));
edg[i].x=u;
edg[i].y=v;
edg[i].w=c;
}
scanf("%d",&q);
Dijkstra(1);
for(int i=1;i<=n;i++){
cnt[i]=dist[i];
}
Dijkstra2(n);
for(int i=1;i<=n;i++){
g[i]=dist[i];
}
for(int i=1;i<=q;i++){
scanf("%d",&x);
l=cnt[edg[x].y]+edg[x].w;//edg前面的路径长度
r=g[edg[x].x];//edg后面的路径长度
sum=l+r;//总的路径长度
if(sum>cnt[n]){
printf("NO\n");
}else{
printf("YES\n");
}
}
return 0;
}