Problem Link
The Problem in short:
Given an undirected weighted graph where each node contains a traffic light. The light shows two colors: Blue and Purple. Blue is visible for t_b seconds and Purple is visible for t_p seconds. This keeps repeating periodically. These two values may differ for different nodes. Cars can cross an edge (u,v) iff both u and v has same color at the moment when the car departs from u to v.
Now, given a source S and a destination T and the initial state of every node (there current color and how much time is remaining for that color), calculate the minimum time to reach from S to T.
Solution:
Run Dijkstra's from S. The tricky part is: given a time t and a node u such that, the current time is t and the car is at u, when will the light at u and the light at v show the same color ?
The Problem in short:
Given an undirected weighted graph where each node contains a traffic light. The light shows two colors: Blue and Purple. Blue is visible for t_b seconds and Purple is visible for t_p seconds. This keeps repeating periodically. These two values may differ for different nodes. Cars can cross an edge (u,v) iff both u and v has same color at the moment when the car departs from u to v.
Now, given a source S and a destination T and the initial state of every node (there current color and how much time is remaining for that color), calculate the minimum time to reach from S to T.
Solution:
Run Dijkstra's from S. The tricky part is: given a time t and a node u such that, the current time is t and the car is at u, when will the light at u and the light at v show the same color ?
#include<stdio.h> #include<string.h> #include<math.h> #include<ctype.h> #include<assert.h> #include<stdlib.h> #include<time.h> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<iostream> #include<algorithm> #include<string> using namespace std; #define FOR(i,n) for(int i=0;i<(n);++i) #define REP(i,a,b) for(int i=(a);i<=(b);++i) #define CLR(a,x) memset(a,(x),sizeof(a)) typedef long long LL; typedef pair<int,int> pii; struct State { int at; int when; State(){} State(int _at, int _when){at = _at; when = _when;} bool operator < (const State other) const { return when > other.when; } }; const int INF = (1<<29); vector<int> adj[305]; int nodes, edges; int cost[305][305]; int from,to; int dist[305], parent[305]; int remaining[305], initColor[305], duration[305][2]; typedef pair<int,int> colorInfo; colorInfo getColorInfo(int u, int t) { if(t < remaining[u]) return colorInfo(initColor[u],remaining[u]-t); int M = duration[u][0]+duration[u][1]; int r = (t-remaining[u])%M; if(r < duration[u][1-initColor[u]]) return colorInfo(1-initColor[u],duration[u][1-initColor[u]]-r); else return colorInfo(initColor[u],duration[u][initColor[u]]-(r-duration[u][1-initColor[u]])); } void getNext4InterestingTime(int u, int t, vector<int>& VT) { VT.push_back(t); colorInfo info = getColorInfo(u,t); t += info.second; VT.push_back(t); FOR(i,4) { if(i%2==0) t += duration[u][1-info.first]; else t += duration[u][info.first]; VT.push_back(t); } } int calcTime(int u, int v, int t) // currently at u, current time t, want to go to v { vector<int> interestingTime; getNext4InterestingTime(u,t,interestingTime); getNext4InterestingTime(v,t,interestingTime); sort(interestingTime.begin(),interestingTime.end()); FOR(i,interestingTime.size()) { if(getColorInfo(u,interestingTime[i]).first == getColorInfo(v,interestingTime[i]).first) return interestingTime[i]; } return -1; } int solve() { REP(i,1,nodes) dist[i] = INF; dist[from] = 0; parent[from] = from; State source(from,0); priority_queue<State> pq; pq.push(source); while(pq.empty()==false) { State u = pq.top(); pq.pop(); if(u.when > dist[u.at]) continue; FOR(i,adj[u.at].size()) { int x = adj[u.at][i]; int y = calcTime(u.at,x,u.when); if(y == -1) continue; y += cost[u.at][x]; if(dist[x] > y) { parent[x] = u.at; dist[x] = y; pq.push(State(x,y)); } } } return dist[to]; } int main() { scanf("%d%d",&from,&to); scanf("%d%d",&nodes,&edges); FOR(i,nodes) { char s[5]; scanf("%s%d%d%d",s,&remaining[i+1],&duration[i+1][0],&duration[i+1][1]); if(s[0]=='B') initColor[i+1] = 0; else initColor[i+1] = 1; } FOR(e,edges) { int u,v,w; scanf("%d%d%d",&u,&v,&w); adj[u].push_back(v); adj[v].push_back(u); cost[u][v] = cost[v][u] = w; } int ans = solve(); if(ans >= INF) { puts("0"); } else { vector<int> path; while(1) { path.push_back(to); if(to==from) break; to = parent[to]; } cout<<ans<<"\n"; for(int i=path.size()-1;i>=0;--i) { printf("%d",path[i]); if(i>0) printf(" "); } puts(""); } return 0; }