• P3008 [USACO11JAN]道路和飞机Roads and Planes


    P3008 [USACO11JAN]道路和飞机Roads and Planes

    Dijkstra+Tarjan

    因为题目有特殊限制所以不用担心负权的问题

    但是朴素的Dijkstra就算用堆优化,也显然会超时。

    这是因为Dj每次扩展时,总是找到费用最小那个点进行扩展。

    而本题的毒瘤数据可以在一个图(设其点数为k)后连一长串负权边。这样每次扩展的最坏复杂度O(n^k),T出天际。

    但是我们又可以用到题目的特殊限制:一个图被限制成若干层,每层的最短路互相无影响

    显然,我们可以用Tarjan缩点法,把图分层,把每层分离出来,单独跑一遍Dj。

    然后就没了。(逃

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cctype>
    using namespace std;
    template <typename T> inline T min(T &a,T &b) {return a<b ?a:b;}
    template <typename T> inline void read(T &x){
        char c=getchar(); x=0; bool f=1;
        while(!isdigit(c)) f= !f||c=='-' ? 0:1,c=getchar();
        while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
        x= f? x:-x;
    }
    int n,m1,m2,s,d[25002],cnt1,hd[25002],nxt[150002],ed[25002],poi[150002],val[150002];
    int dfs_clock,cnt2,_top,low[25002],dfn[25002],be[25002],st[25002]; //用于Tarjan
    struct data{
        int d,u;
        bool operator < (const data &tmp) const {
            if(be[u]!=be[tmp.u]) return be[u]<be[tmp.u]; //同块内先处理
            return d>tmp.d;
        }
    }; priority_queue <data> h;
    inline void add(int x,int y,int v){
        nxt[ed[x]]=++cnt1; hd[x]= hd[x] ? hd[x]:cnt1;
        ed[x]=cnt1; poi[cnt1]=y; val[cnt1]=v;
    }
    inline void tarjan(int x){ //Tarjan模板,可右转P3387
        dfn[x]=low[x]=++dfs_clock; st[++_top]=x;
        for(int i=hd[x];i;i=nxt[i]){
            int to=poi[i];
            if(!dfn[to]) tarjan(to),low[x]=min(low[x],low[to]);
            else if(!be[to]) low[x]=min(low[x],dfn[to]);
        }
        if(low[x]==dfn[x]){ //给出每个点所处层的编号
            be[x]=++cnt2;
            while(st[_top]!=x) be[st[_top--]]=cnt2;
            --_top;
        }
    }
    void dijkstra(){ //裸的
        memset(d,127,sizeof(d));
        h.push((data){d[s]=0,s});
        while(!h.empty()){
            data x=h.top(); h.pop();
            if(x.d!=d[x.u]) continue;
            for(int i=hd[x.u];i;i=nxt[i])
                if(x.d+val[i]<d[poi[i]]){
                    d[poi[i]]=x.d+val[i];
                    h.push((data){d[poi[i]],poi[i]});
                }
        }
    }
    int main(){
        read(n); read(m1); read(m2); read(s); int q1,q2,q3;
        for(int i=1;i<=m1;++i) read(q1),read(q2),read(q3),add(q1,q2,q3),add(q2,q1,q3);
        for(int i=1;i<=m2;++i) read(q1),read(q2),read(q3),add(q1,q2,q3);
        tarjan(s); //tarjan缩点
        for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
        dijkstra();
        for(int i=1;i<=n;++i){
            if(d[i]==d[0]) printf("NO PATH
    ");
            else printf("%d
    ",d[i]);
        }return 0;
    }
  • 相关阅读:
    持久化 轻量数据
    ObjectiveC 中 +load 与 +initialize
    对待“技术“与“管理”的想法
    springcloudalibaba之Nacos
    Docker上安装Redis
    Docker安装Minio
    基于Docker部署Nacos
    支付宝微信合单支付
    Nacos安装和配置
    windows常用软件安装和配置
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9686113.html
Copyright © 2020-2023  润新知