题意:给定一个无向图,你从结点1开始走,每经过一条边需要1的时间,每条边都有一个开放时间,只有当目前所用的时间大于等于开放时间时,这条边才可以被经过。每一单位时间你都必须经过一条边,问最快什么时候可以到达N
一开始觉得当一条边未开放时,最优的策略便是在当前结点和上次经过的结点间徘徊,知道结点开放,于是最少的徘徊次数便是那条边的边权。后面发现奇偶性其实会影响答案。于是将dis分为奇偶跑pb_ds优化的dijkstra即可。
PS:比赛时竟然有人三分钟把这道题切了,再一次证明了我好菜233333
#include<bits/stdc++.h> #include<ext/pb_ds/priority_queue.hpp> using namespace std; #define MAXN 10000+10 typedef long long LL; const LL INF=99999999999999; struct edge{int v,next;LL w;}edge[MAXN*4]; struct Ed{ int u,p;LL w; Ed(){} Ed(int u,int p,LL w):u(u),p(p),w(w){} bool operator >(const Ed &a)const{return w>a.w;} }; typedef __gnu_pbds::priority_queue<Ed,greater<Ed>,__gnu_pbds::thin_heap_tag>heap; int n,m,head[MAXN],un[MAXN][2]; LL dis[MAXN][2]; heap::point_iterator it[MAXN][2]; heap q; void add(int u,int v,LL w){ static int tot=0; edge[++tot].v=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot; } LL val(LL x,LL y){ if(x>=y)return 0; return ((y-x)&1)?(y-x+2):y-x+1; } void dijkstra(){ for(int i=1;i<=n;i++)dis[i][0]=dis[i][1]=INF; dis[1][0]=0; for(int i=1;i<=n;i++){ it[i][0]=q.push((Ed){i,0,dis[i][0]}); it[i][1]=q.push((Ed){i,1,dis[i][1]}); } q.push((Ed){1,0,0}); while(!q.empty()){ int u=q.top().u,p=q.top().p; q.pop(); if(un[u][p])continue; un[u][p]=1; for(int i=head[u];i;i=edge[i].next){ int v=edge[i].v,w; w=max(1LL,val(dis[u][p],edge[i].w)); LL tmp=dis[u][p]+w; if(!un[v][tmp&1]&&dis[u][p]+w<dis[v][tmp&1]){ dis[v][tmp&1]=tmp; q.modify(it[v][tmp&1],(Ed){v,tmp&1,dis[v][tmp&1]}); } } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v;LL w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w);add(v,u,w); } dijkstra(); if(min(dis[n][1],dis[n][0])==INF)printf("-1 "); else printf("%lld ",min(dis[n][1],dis[n][0])); return 0; }