Dijkstra/Tarjan-关键边题解

题目描述

总统要回家,即从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

样例可以自己参考一下图片过一遍,加深影响喵!

顺便推荐一下猫猫画图用的网站喵!免费喵!

Graph Editor

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;
}
posted @ 2024-02-03 11:25  Firepaw喵喵喵  阅读(25)  评论(0)    收藏  举报