码迷,mamicode.com
首页 > Windows程序 > 详细

AcWing342 道路与航线(最短路+DAG)

时间:2020-05-03 10:53:02      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:cst   play   show   oid   而在   cond   int   ++   hid   

这道题有负权边,本来考虑可以用spfa,但是这个算法被卡了,因此只能转换思路。

我们发现因为负权边是单向的,且没有环,而正权是有环的,这说明这个图是一块一块的,负权边就是联通块和块的,因此这构成一个DAG

我们考虑在块内部使用迪杰斯特拉算法而在块和块之间使用拓扑排序来做

技术图片
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define x first
#define y second
using namespace std;
typedef pair<int,int> pll;
const int N=1e5+10;
const int inf=0x3f3f3f3f;
vector<int> g[N];
int id[N],e[N],ne[N],w[N],h[N],idx;
bool st[N];
int t,r,p,s;
int bcnt;
int in[N];
queue<int> q;
int dis[N];
void add(int a,int b,int c){
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void dfs(int x,int bcnt){
    id[x]=bcnt;
    g[bcnt].push_back(x);
    int i;
    for(i=h[x];i!=-1;i=ne[i]){
        int j=e[i];
        if(!id[j])
        dfs(j,bcnt);
    }
}
void dij(int t){
    priority_queue<pll,vector<pll>,greater<pll> > pq;
    for(auto x:g[t]){
        pq.push({dis[x],x});// all in beacause it will contribute to the next block
    }
    while(pq.size()){
        auto u=pq.top();
        pq.pop();
        int ver=u.y,distance=u.x;
        if(st[ver])
        continue;
        st[ver]=1;
        int i;
        for(i=h[ver];i!=-1;i=ne[i]){
            int j=e[i];
            if(dis[j]>dis[ver]+w[i]){
                dis[j]=dis[ver]+w[i];
                if(id[j]==id[ver]){
                    pq.push({dis[j],j});
                }
            }
            if(id[j]!=id[ver]&&--in[id[j]]==0) q.push(id[j]);
        }
    }
}
void topo(int x){
    int i;
    memset(dis,0x3f,sizeof dis);
    dis[x]=0;
    for(i=1;i<=bcnt;i++){
        if(!in[i]){
            q.push(i);
        }
    }
    while(q.size()){
        int t=q.front();
        q.pop();
        dij(t);
    }
}
int main(){
    cin>>t>>r>>p>>s;
    int i;
    memset(h,-1,sizeof h);
    for(i=1;i<=r;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
        add(b,a,c);
    }
    for(i=1;i<=t;i++){
        if(!id[i]){
            bcnt++;
            dfs(i,bcnt);
        }
    }
    for(i=1;i<=p;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
        in[id[b]]++;
    }
    topo(s);
    for(i=1;i<=t;i++){
        if(dis[i]>inf/2)
        cout<<"NO PATH"<<endl;
        else
        cout<<dis[i]<<endl;
    }
}
View Code

 

AcWing342 道路与航线(最短路+DAG)

标签:cst   play   show   oid   而在   cond   int   ++   hid   

原文地址:https://www.cnblogs.com/ctyakwf/p/12820767.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!