zoukankan      html  css  js  c++  java
  • AcWing342 道路与航线(最短路+DAG)

    这道题有负权边,本来考虑可以用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
  • 相关阅读:
    10 种保护 Spring Boot 应用的绝佳方法
    Redis 如何分析慢查询操作?
    Spring Boot 主类及目录结构介绍
    Redis 再牛逼,也得设置密码!!
    Spring Data Redis 详解及实战一文搞定
    Spring Boot Redis Cluster 实战干货
    超详细的 Redis Cluster 官方集群搭建指南
    Redis Linux 安装运行实战全记录
    hdu 4790 Just Random (思路+分类计算+数学)
    poj 1328 Radar Installation(贪心)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12820767.html
Copyright © 2011-2022 走看看