题目描述
总统要回家,即从s走到t,会经过一些街道,每条街道都是单向的并且拥有权值。现在,为了让总统更好的回家,要对每一条街道进行操作:
①如果该街道一定在最短路上,则输出“YES”。
②如果该街道修理过后,该边所在的最短路可以取代原先的最短路,则输出“CAN x”,x是修改该街道的最小花费,就是权值减小的值。
③如果该街道不在s到t的路径上,或者修改过后权值小于等于0,则输出“NO”。
样例
样例输入
6 7 1 6
1 2 2
1 3 1
1 5 4
3 5 3
2 5 5
2 4 2
5 6 1
样例输出
NO
NO
CAN 1
CAN 1
CAN 4
NO
YES
思路
Dijkstra + Tarjan
priority queue + pair
样例可以自己参考一下图片过一遍,加深影响喵!
顺便推荐一下猫猫画图用的网站喵!免费喵!
code
#include <bits/stdc++.h>
#define ll long long
#define oo 2000000000
using namespace std;
long long a[100005],b[100005],l[100005],d1[100005],d2[100005],dfn[100005],low[100005],n,m,s,t,id;
bool bridge[100005],vis[100005];
vector<pair<long long,long long>> edge[100005];
void dijkstra(long long v,long long *d){
long long t;
priority_queue<pair<long long,long long>,vector<pair<long long,long long>>,greater<pair<long long,long long>>> q;
for(long long i=1;i<=n;i++) d[i]=oo;
d[v]=0;q.push(make_pair(0,v));
while(!q.empty()){
t=q.top().second;q.pop();
for(long long i=0;i<edge[t].size();i++){
if(d[edge[t][i].first]>d[t]+edge[t][i].second){
d[edge[t][i].first]=d[t]+edge[t][i].second;
q.push(make_pair(d[edge[t][i].first],edge[t][i].first));
}
}
}
return;
}
void tarjan(long long x){
id++;
dfn[x]=id;
low[x]=id;
for(long long i=0;i<edge[x].size();i++){
if(vis[edge[x][i].second]) continue;
vis[edge[x][i].second]=true;
if(!dfn[edge[x][i].first]){
tarjan(edge[x][i].first);
low[x]=min(low[x],low[edge[x][i].first]);
if(dfn[x]<low[edge[x][i].first]) bridge[edge[x][i].second]=true;
}
else low[x]=min(low[x],dfn[edge[x][i].first]);
}
return;
}
int main(){
cin>>n>>m>>s>>t;
for(long long i=0;i<m;i++) cin>>a[i]>>b[i]>>l[i];
for(long long i=0;i<m;i++) edge[a[i]].push_back(make_pair(b[i],l[i]));
dijkstra(s,d1);
for(long long i=1;i<=n;i++) edge[i].clear();
for(long long i=0;i<m;i++) edge[b[i]].push_back(make_pair(a[i],l[i]));
dijkstra(t,d2);
for(long long i=1;i<=n;i++) edge[i].clear();
for(long long i=0;i<m;i++){
if(d1[a[i]]+l[i]+d2[b[i]]==d1[t]){
edge[a[i]].push_back(make_pair(b[i],i));
edge[b[i]].push_back(make_pair(a[i],i));
}
}
tarjan(s);
for(long long i=0;i<m;i++){
if(bridge[i]) cout<<"YES"<<endl;
else if(d1[t]-d1[a[i]]-d2[b[i]]-1>0) cout<<"CAN "<<l[i]-(d1[t]-d1[a[i]]-d2[b[i]]-1)<<endl;
else cout<<"NO"<<endl;
}
return 0;
}
标签:Tarjan,样例,long,100005,Dijkstra,edge,街道,关键,id
From: https://www.cnblogs.com/Firepaw-cattery/p/18004466