bzoj1922 [Sdoi2010]大陆争霸(Dijstra+贪心)

Dijkstra,有一些先后顺序的限制。
dis1[i]表示能到i的最早时间,dis2[i]表示能进入i的最早时间(即它的保护装置所在地都到达了的最早时间)
实际的最早到达时间就是max(dis1[i],dis2[i])。
跑Dij时没有被解除限制的城市先不入堆即可。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 3010
#define pa pair<ll,int>
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,h[N],num=0,du[N];
ll dis1[N],dis2[N];
bool vis[N];
struct edge{
    int to,next,val;
}data[70010];
vector<int>a[N];
inline void Dij(){
    priority_queue<pa,vector<pa>,greater<pa> >q;memset(dis1,inf,sizeof(dis1));
    q.push(make_pair(0,1));dis1[1]=0;
    while(!q.empty()){
        int x=q.top().second;ll val=q.top().first;q.pop();
        if(vis[x]) continue;vis[x]=1;
        for(int i=h[x];i;i=data[i].next){
            int y=data[i].to;
            if(val+data[i].val<dis1[y]){
                dis1[y]=val+data[i].val;
                if(!du[y]) q.push(make_pair(max(dis1[y],dis2[y]),y));
            }
        }for(int i=0;i<a[x].size();++i){
            int y=a[x][i];--du[y];dis2[y]=max(dis2[y],val);
            if(!du[y]) q.push(make_pair(max(dis1[y],dis2[y]),y));
        }
    }
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=m;++i){
        int x=read(),y=read(),val=read();
        data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].val=val;
    }for(int i=1;i<=n;++i){
        du[i]=read();
        for(int j=1;j<=du[i];++j) a[read()].push_back(i);
    }Dij();printf("%lld\n",max(dis1[n],dis2[n]));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80733226