【bzoj 1922】大陸爭霸(Dijkstra堆優化)

傳送門biu~
對於每個節點,dis1表示走到這個點的最早時間,dis2代表解除了有關這個點的所有限制的最早時間,所以每個點最早到達時間爲max(dis1,dis2)。在Dijkstra時,每到一個節點,就解除這個點對其它點的保護,當一個點的所有限制都被解除時,可以入堆。

#include<bits/stdc++.h>
#define N 3005
#define M 70005
#define pa pair<int,int>
using namespace std;
int n,m,dis1[N],dis2[N],d[N];bool vis[N];
int head[N],nex[M],to[M],val[M],tp;
vector<int>e[N];
inline void add(int x,int y,int z){
    nex[++tp]=head[x];
    head[x]=tp;
    to[tp]=y;
    val[tp]=z;
}
priority_queue<pa,vector<pa>,greater<pa> >q;
inline void Dijkstra(){
    memset(dis1,0x3f,sizeof dis1);
    dis1[1]=0;q.push(pa(0,1));
    while(!q.empty()){
        int x=q.top().second;q.pop();
        if(vis[x])  continue;
        vis[x]=true;
        int now=max(dis1[x],dis2[x]);
        for(int i=head[x];i;i=nex[i]){
            if(now+val[i]<dis1[to[i]]){
                dis1[to[i]]=now+val[i];
                if(!d[to[i]])   q.push(pa(dis1[to[i]],to[i]));
            }
        }
        for(int i=0;i<e[x].size();++i){
            int v=e[x][i];
            dis2[v]=max(dis2[v],now);
            if(!--d[v]) q.push(pa(max(dis1[v],dis2[v]),v));
        }
    }
    printf("%d\n",max(dis1[n],dis2[n]));
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    for(int i=1;i<=n;++i){
        scanf("%d",&d[i]);
        for(int j=1;j<=d[i];++j){
            int x;
            scanf("%d",&x);
            e[x].push_back(i);
        }
    }
    Dijkstra();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章