题意:有编号1~n(2<=n<=10^5)的星球,在不用的星球间共有m(0<=m<=10^5)个传送门,任意两个星球间传送门不超过1个,每个传送门需要花费
一定的时间,但是在某时刻会在某星球有旅客到达,这时要一定等到没有旅客到达的时候才能出发,问从1走到n最少花费时间是多少。
题解:对于每一个星球的每一个到达的人的时刻预处理出来下一个可行的时刻,然后进行Dijkstra即可,注意最后到达n的时候不需要等到下一个可行时刻了唉。
Sure原创,转载请注明出处
#include <iostream> #include <cstdio> #include <memory.h> #include <vector> #include <queue> #define MIN(a , b) ((a) < (b) ? (a) : (b)) #define MAX(a , b) ((a) > (b) ? (a) : (b)) using namespace std; const int maxn = 100010; struct node { int v,next; __int64 w; }edge[maxn << 1]; struct fff { __int64 ti,next; }; struct ddd { int v; __int64 val; bool operator < (const ddd &other) const { return val > other.val; } }; vector <fff> gate[maxn]; priority_queue <ddd> Q; int head[maxn]; __int64 dis[maxn]; bool vis[maxn]; int m,n,idx; void init() { memset(head,-1,sizeof(head)); memset(dis,-1,sizeof(dis)); memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++) { gate[i].clear(); } while(!Q.empty()) { Q.pop(); } idx = 0; return; } void addedge(int u,int v,__int64 w) { edge[idx].v = v; edge[idx].w = w; edge[idx].next = head[u]; head[u] = idx++; edge[idx].v = u; edge[idx].w = w; edge[idx].next = head[v]; head[v] = idx++; return; } void read() { int num,u,v; __int64 w; fff tmp; for(int i=0;i<m;i++) { scanf("%d %d %I64d",&u,&v,&w); addedge(u,v,w); } for(int i=1;i<=n;i++) { scanf("%d",&num); for(int j=0;j<num;j++) { scanf("%I64d",&tmp.ti); tmp.next = 0; gate[i].push_back(tmp); } for(int j=num-1;j>=0;j--) { if(j == num-1 || gate[i][j].ti < gate[i][j+1].ti - 1) { gate[i][j].next = gate[i][j].ti+1; } else gate[i][j].next = gate[i][j+1].next; } } return; } __int64 bis(__int64 val,int id) { int l = 0,r = (int)gate[id].size()-1; while(l <= r) { int mid = (l + r) >> 1; if(gate[id][mid].ti == val) return gate[id][mid].next; else if(gate[id][mid].ti > val) r = mid - 1; else l = mid + 1; } return val; } void solve() { ddd cur,tmp; tmp.v = 1; tmp.val = bis(0,1); Q.push(tmp); while(!Q.empty()) { cur = Q.top(); Q.pop(); if(cur.v == n) { printf("%I64d\n",cur.val); return; } if(vis[cur.v] == false) { vis[cur.v] = true; for(int i=head[cur.v];i != -1;i=edge[i].next) { __int64 tt; if(edge[i].v == n) tt = cur.val + edge[i].w; else tt = bis(cur.val + edge[i].w , edge[i].v); if(vis[edge[i].v] == false && (dis[edge[i].v] == -1 || dis[edge[i].v] > tt)) { dis[edge[i].v] = tt; tmp.v = edge[i].v; tmp.val = tt; Q.push(tmp); } } } } puts("-1"); return; } int main() { while(~scanf("%d %d",&n,&m)) { init(); read(); solve(); } return 0; }