<|instruction|>
Solve the below problem. The solution should start with an abridged problem statement. Then key observations. Then full solution based on the observations. Then C++ and Python implementations with comments.

103. Traffic Lights
Time limit per test: 0.25 second(s)
Memory limit: 4096 kilobytes
input: standard
output: standard



In the city of Dingilville the traffic is arranged in an unusual way. There are junctions and roads connecting the junctions. There is at most one road between any two different junctions. There is no road connecting a junction to itself. Travel time for a road is the same for both directions. At every junction there is a single traffic light that is either blue or purple at any moment. The color of each light alternates periodically: blue for certain duration and then purple for another duration. Traffic is permitted to travel down the road between any two junctions, if and only if the lights at both junctions are the same color at the moment of departing from one junction for the other. If a vehicle arrives at a junction just at the moment the lights switch it must consider the new colors of lights. Vehicles are allowed to wait at the junctions. You are given the city map which shows:
the travel times for all roads (integers)
the durations of the two colors at each junction (integers)
and the initial color of the light and the remaining time (integer) for this color to change at each junction.

Your task is to find a path which takes the minimum time from a given source junction to a given destination junction for a vehicle when the traffic starts. In case more than one such path exists you are required to report only one of them.

Input
The first line contains two numbers: The id-number of the source junction and the id-number of the destination junction. The second line contains two numbers: N, M. The following N lines contain information on N junctions. The (i+2)'th line of the input file holds information about the junction i : Ci, riC, tiB, tiP where Ci is either B for blue or P for purple, indicating the initial color of the light at the junction i. Finally, the next M lines contain information on M roads. Each line is of the form: i, j, lij where i and j are the id-numbers of the junctions which are connected by this road. 2 ≤ N ≤ 300 where N is the number of junctions. The junctions are identified by integers 1 through N. These numbers are called id-numbers. 1 ≤ M ≤ 14000 where M is the number of roads. 1 ≤ lij ≤ 100 where lij is the time required to move from junction i to j using the road that connects i and j. 1 ≤ tiC ≤ 100 where tiC is the duration of the color c for the light at the junction i. The index c is either 'B' for blue or 'P' for purple. 1 ≤ riC ≤ tiC where riC is the remaining time for the initial color c at junction i.

Output
If a path exists:
The first line will contain the time taken by a minimum-time path from the source junction to the destination junction.
Second line will contain the list of junctions that construct the minimum-time path you have found. You have to write the junctions to the output file in the order of travelling. Therefore the first integer in this line must be the id-number of the source junction and the last one the id-number of the destination junction.

If a path does not exist:
A single line containing only the integer 0.

Example(s)
sample input
sample output
1 4
4 5
B 2 16 99
P 6 32 13
P 2 87 4
P 38 96 49
1 2 4
1 3 40
2 3 75
2 4 76
3 4 77
127
1 2 4

<|response|>
1. Abridged Problem Statement  
You are given an undirected graph with N junctions (nodes) and M roads (edges). Each junction i has a traffic light that alternates between blue (duration tB_i) and purple (duration tP_i), starting in color C_i with r_i time units remaining in that initial color. You can wait at junctions for free. You may traverse an edge (u, v) of travel time w only at a departure time T when both lights at u and v display the same color. Your goal is to get from a given source S to a destination D in the minimum possible time, and output that time plus one valid path. If no feasible path exists, print 0.

2. Key Observations  
- The availability of an edge (u, v) depends on your departure time T, because you need both lights to match at that instant.  
- Each light has a simple periodic schedule with an “initial segment” of length r_i (the remaining time in C_i), then it alternates indefinitely in blocks of lengths tB_i and tP_i.  
- We can write a function get_color(i, T) that returns the color (blue/purple) at junction i at global time T, and another function time_to_next_change(i, T) giving the wait until the next color switch.  
- To traverse (u, v) from time T, we may have to wait at u until the earliest T' ≥ T such that get_color(u, T') == get_color(v, T'). That T' can be found by “stepping forward” to the next switch of u or v (whichever is sooner), and repeating until colors match (in practice only a few steps).  
- Once we can compute the earliest departure T' for each neighbor v from u at current time T, we have a time‐dependent edge weight T' + w(u,v). We can plug this into a standard Dijkstra’s algorithm by treating the cost to reach v as that arrival time.  
- We record a parent[v] pointer whenever we improve dist[v] so that we can reconstruct the path at the end.

3. Full Solution Approach  
a. Data Structures  
   - Store for each junction i:  
     • isBlueInit[i]: true if initial color is blue, false if purple  
     • remInit[i]: remaining time in that initial color  
     • tB[i], tP[i]: durations of blue and purple phases  
   - Adjacency list: for each u, vector of (v, w_uv).  
   - Arrays dist[i] = best known arrival time at i, initialized to ∞ except dist[S] = 0.  
   - parent[i] = predecessor of i on the best path.  

b. Functions on Light Phases  
   1. get_color(i, T):  
      - If T < remInit[i], return isBlueInit[i].  
      - Else let T' = T − remInit[i], cycle = tB[i] + tP[i]. Let x = T' mod cycle.  
        If initial was blue then the first block after remInit is purple of length tP[i], otherwise the first block is blue of length tB[i]. Use x to decide.  
   2. time_to_next_change(i, T):  
      - If T < remInit[i], return remInit[i] - T.  
      - Else let T' = T − remInit[i], cycle = tB[i] + tP[i], x = T' mod cycle.  
        Depending on which sub-block x lies in (blue or purple), return the remaining time until that sub-block ends.  

c. Synchronizing Two Junctions  
   first_sync_time(u, v, T):  
      - Repeat up to a small constant number of times (e.g. 3):  
         • If get_color(u, T) == get_color(v, T), return T.  
         • Otherwise compute du = time_to_next_change(u, T), dv = time_to_next_change(v, T), and advance T by min(du, dv).  
      - If still no match, return −1 (treat as “never synchronizes soon”).  

d. Time‐Dependent Dijkstra  
   - Use a min‐heap keyed by current known arrival time.  
   - Pop (t, u). If t > dist[u], skip (stale).  
   - For each neighbor (v, w):  
     • let depart = first_sync_time(u, v, t). If depart<0, skip.  
     • let arrive = depart + w. If arrive < dist[v], update dist[v]=arrive, parent[v]=u, push (arrive, v).  
   - Continue until heap is empty or you have settled D.  

e. Output  
   - If dist[D] is still ∞, print 0.  
   - Otherwise print dist[D] on the first line. Reconstruct the path by following parent[] from D back to S, reverse it, and print the sequence of junction IDs (1‐based).

4. C++ Implementation with Detailed Comments  
```cpp
#include <bits/stdc++.h>
using namespace std;

// We store for each junction: 
//   isBlueInit: initial color flag
//   remInit:    remaining time in that initial phase
//   tB, tP:     durations of blue and purple phases
struct Junction {
    bool isBlueInit;
    int remInit;
    int tB, tP;
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int S, D;
    cin >> S >> D;
    // convert to 0-based
    --S; --D;

    int N, M;
    cin >> N >> M;

    vector<Junction> J(N);
    for(int i = 0; i < N; i++){
        char C;
        int r, b, p;
        cin >> C >> r >> b >> p;
        J[i].isBlueInit = (C == 'B');
        J[i].remInit     = r;
        J[i].tB          = b;
        J[i].tP          = p;
    }

    // adjacency list: (neighbor, travel_time)
    vector<vector<pair<int,int>>> adj(N);
    for(int i = 0; i < M; i++){
        int u, v, w;
        cin >> u >> v >> w;
        --u; --v;
        adj[u].push_back({v,w});
        adj[v].push_back({u,w});
    }

    // Function to get color at junction u at time T.
    // Returns true=blue, false=purple
    auto get_color = [&](int u, int T){
        auto &q = J[u];
        // still in the initial block?
        if(T < q.remInit){
            return q.isBlueInit;
        }
        // subtract the initial block
        T -= q.remInit;
        int cycle = q.tB + q.tP;
        int x = T % cycle;
        // if initial was blue, the _next_ block is purple, else blue
        if(q.isBlueInit){
            if(x < q.tP)       return false; // in purple
            x -= q.tP;
            return (x < q.tB);                // in blue
        } else {
            if(x < q.tB)       return true;  // in blue
            x -= q.tB;
            return (x >= q.tP ? true : false); // after purple block we loop
        }
    };

    // Time until junction u next changes its light, if currently at time T
    auto time_to_next_change = [&](int u, int T){
        auto &q = J[u];
        if(T < q.remInit){
            return q.remInit - T;
        }
        T -= q.remInit;
        int cycle = q.tB + q.tP;
        int x = T % cycle;
        if(q.isBlueInit){
            // first in purple
            if(x < q.tP)  return q.tP - x;
            x -= q.tP;
            // then in blue
            return q.tB - x;
        } else {
            // first in blue
            if(x < q.tB)  return q.tB - x;
            x -= q.tB;
            // then in purple
            return q.tP - x;
        }
    };

    // Find earliest T' >= T when u and v have the same color, or -1 if not in a few steps.
    function<int(int,int,int)> first_sync = [&](int u, int v, int T){
        for(int it = 0; it < 3; it++){
            if(get_color(u, T) == get_color(v, T))
                return T;
            int du = time_to_next_change(u, T);
            int dv = time_to_next_change(v, T);
            T += min(du, dv);
        }
        return -1;
    };

    const int INF = 1e9;
    vector<int> dist(N, INF), parent(N, -1);
    dist[S] = 0;

    // Min-heap of (arrival_time, node)
    priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>> pq;
    pq.push({0, S});

    while(!pq.empty()){
        auto [t, u] = pq.top();
        pq.pop();
        if(t > dist[u]) continue; // stale

        // relax all edges
        for(auto &ed : adj[u]){
            int v = ed.first, w = ed.second;
            int depart = first_sync(u, v, t);
            if(depart < 0) continue;                // never sync soon
            int arrive = depart + w;
            if(arrive < dist[v]){
                dist[v] = arrive;
                parent[v] = u;
                pq.push({arrive, v});
            }
        }
    }

    if(dist[D] == INF){
        cout << 0 << "\n";
        return 0;
    }

    // reconstruct path S → ... → D
    vector<int> path;
    for(int cur = D; cur != -1; cur = parent[cur]){
        path.push_back(cur+1);  // back to 1-based
    }
    reverse(path.begin(), path.end());

    cout << dist[D] << "\n";
    for(int x : path) cout << x << " ";
    cout << "\n";
    return 0;
}
```

5. Python Implementation with Detailed Comments  
```python
import sys
import heapq

def read_input():
    data = sys.stdin.read().split()
    it = iter(data)
    S = int(next(it)) - 1
    D = int(next(it)) - 1
    N = int(next(it))
    M = int(next(it))
    # Junction array: each entry is (isBlueInit, remInit, tB, tP)
    J = []
    for _ in range(N):
        C = next(it)
        r = int(next(it))
        b = int(next(it))
        p = int(next(it))
        J.append((C=='B', r, b, p))
    adj = [[] for _ in range(N)]
    for _ in range(M):
        u = int(next(it)) - 1
        v = int(next(it)) - 1
        w = int(next(it))
        adj[u].append((v,w))
        adj[v].append((u,w))
    return S, D, N, J, adj

def get_color(u, T, J):
    isBlue, r, tB, tP = J[u]
    # still in initial block?
    if T < r:
        return isBlue
    T -= r
    cycle = tB + tP
    x = T % cycle
    if isBlue:
        # next block is purple
        if x < tP:
            return False
        x -= tP
        return x < tB
    else:
        # next block is blue
        if x < tB:
            return True
        x -= tB
        return x >= tP  # loops back

def time_to_next_change(u, T, J):
    isBlue, r, tB, tP = J[u]
    if T < r:
        return r - T
    T -= r
    cycle = tB + tP
    x = T % cycle
    if isBlue:
        if x < tP:
            return tP - x
        x -= tP
        return tB - x
    else:
        if x < tB:
            return tB - x
        x -= tB
        return tP - x

def first_sync(u, v, T, J):
    # Try a few phase‐change steps
    for _ in range(3):
        if get_color(u, T, J) == get_color(v, T, J):
            return T
        du = time_to_next_change(u, T, J)
        dv = time_to_next_change(v, T, J)
        T += min(du, dv)
    return -1

def solve():
    S, D, N, J, adj = read_input()
    INF = 10**18
    dist = [INF]*N
    parent = [-1]*N
    dist[S] = 0
    pq = [(0, S)]

    while pq:
        t, u = heapq.heappop(pq)
        if t > dist[u]:
            continue
        for v, w in adj[u]:
            depart = first_sync(u, v, t, J)
            if depart < 0:
                continue
            arrive = depart + w
            if arrive < dist[v]:
                dist[v] = arrive
                parent[v] = u
                heapq.heappush(pq, (arrive, v))

    if dist[D] == INF:
        print(0)
        return

    # Reconstruct path
    path = []
    cur = D
    while cur != -1:
        path.append(cur+1)
        cur = parent[cur]
    path.reverse()

    print(dist[D])
    print(*path)

if __name__ == "__main__":
    solve()
```

Explanation Highlights:  
- We treat light‐color constraints as a time‐dependent edge availability.  
- Computing the next feasible departure time between two junctions takes only a few O(1) steps.  
- A modified Dijkstra with those dynamic edge‐cost computations still runs in O((N+M) log N), efficient for N≤300, M≤14 000.