zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    JAVA BIO至NIO演进
    spring源码分析系列 (15) 设计模式解析
    java设计模式解析(1) Observer观察者模式
    spring源码分析系列 (8) FactoryBean工厂类机制
    spring如何解决单例循环依赖问题?
    spring源码分析系列
    java引用类型简述
    Redis简单延时队列
    MYSQL时间类别总结: TIMESTAMP、DATETIME、DATE、TIME、YEAR
    虚拟机安装centos7
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9686113.html
Copyright © 2011-2022 走看看