• [SDOI2010]大陆争霸


    Solution

    有些城市必须在某些城市被破坏之后才能进入,例如 (v) 必须在 (u) 之前到,那么 (v) 的最短路就必须先被更新,这实际上是一个拓扑关系。我们必须要同时满足拓扑图的更新顺序和 Dijstra 的贪心策略。这个问题的解决办法就是在跑最短路的时候同时维护拓扑图的更新,当拓扑图中一个节点 (u) 的所有前驱都被更新后,才能将 (u) 加入到最短路更新队列,这样就保证了正确性。

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #include<queue>
    using namespace std;
    #define N 3007
    #define M 700007
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    struct Node{
        int pos,dis;
        Node(int pos_=0,int dis_=0):pos(pos_),dis(dis_){}
        bool operator <(const Node &X)const{return X.dis<dis;}
    };
    
    struct E{
        int next,to,dis;
    }e[M<<1];
    int head[N],cnt=0,tot[N],to[N][N];
    
    priority_queue<Node> Q;
    
    inline void add(int id,int to,int dis){
        e[++cnt]=(E){head[id],to,dis};
        head[id]=cnt;
    }
    
    bool vis[N];
    int n,m,in[N],ans[N],dis[N],lim[N];
    int main(){
        n=read(),m=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read(),d=read();
            add(u,v,d);
        }
        for(int i=1;i<=n;i++){
            in[i]=read();
            for(int j=1;j<=in[i];j++){
                int v=read();
                to[v][++tot[v]]=i;
            }
        }
        memset(dis,63,sizeof(dis));
        dis[1]=ans[1]=0,Q.push(Node(1,0));
        while(!Q.empty()){
            Node t=Q.top(); Q.pop();
            int u=t.pos;
            if(vis[u]) continue;
            else vis[u]=1;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(dis[v]>ans[u]+e[i].dis){
                    dis[v]=ans[u]+e[i].dis;
                    if(!in[v]){
                        ans[v]=max(dis[v],lim[v]);
                        Q.push(Node(v,ans[v]));
                    }
                }
            }
            for(int i=1;i<=tot[u];i++){
                int v=to[u][i];
                lim[v]=max(lim[v],ans[u]);
                if(!(--in[v])){
                    ans[v]=max(dis[v],lim[v]);
                    Q.push(Node(v,ans[v]));
                }
            }
        }
        printf("%d",ans[n]);
    }
    /*
    6 6
    1 2 1
    1 4 3
    2 3 1
    2 5 2
    4 6 2
    5 3 2
    0
    0
    0
    1 3
    0
    2 3 5
    */
    
  • 相关阅读:
    oracle 安装
    C++中 接口的定义 COM
    linux查看及改变运行级别
    BSD Apache GPL LGPL MIT
    DES MAC PIN HEX
    c语言字符输出格式化
    oracle
    Windows C++ 子目录数量
    GetProcAddress 宏
    How do I install Adobe Flash on Debian Wheezy?
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14342889.html
Copyright © 2020-2023  润新知