• 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
  • 相关阅读:
    安装VS 2015完成后,VS2012 打开报错
    ASP.NET MVC 项目中 一般处理程序ashx 获取Session
    windows平台 查看 dll 程序集 PublicKeyToken
    MySQL 表与字段编码格式报错
    Linux系统下安装MongoDB 指南
    ASP.NET 访问路径 错误提示 HTTP 错误 404.8 原来路径中包含bin目录被拒绝
    ASP.NET 大文件上传
    将类型(int,string,…)转换为 T 类型
    直接插入排序
    MySQL 优化之索引合并(index_merge)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12820767.html
Copyright © 2020-2023  润新知