1
+ #include < iostream>
2
+ #include < vector>
3
+ #include < queue>
4
+ using namespace std ;
5
+
6
+ // 1. use topology algorithm to check if graph is a DAG.
7
+ // 2. construct a convergence start point to link all points which in degree is 0.
8
+ // 3. call dijsktra algo to find all short distance from convergence start point.
9
+
10
+ const int MAXN = 0x3fffffff ;
11
+
12
+ class Node {
13
+ public:
14
+ int t, s, d;
15
+ };
16
+
17
+ vector<vector<Node>> G;
18
+ vector<int > pre;
19
+ vector<bool > hasInDegree;
20
+
21
+ bool isDAG () {
22
+ vector<int > inDegree (G.size (), 0 );
23
+ for (int i = 0 ; i < G.size (); i++) {
24
+ for (int j = 0 ; j < G[i].size (); j++) {
25
+ inDegree[G[i][j].t ]++;
26
+ }
27
+ }
28
+
29
+ queue<int > q;
30
+ for (int i = 0 ; i < G.size (); i++) {
31
+ if (inDegree[i] == 0 ) q.push (i);
32
+ }
33
+
34
+ int cnt = 0 ;
35
+ while (!q.empty ()) {
36
+ int u = q.front ();
37
+ q.pop ();
38
+ cnt++;
39
+ for (int i = 0 ; i < G[u].size (); i++) {
40
+ int v = G[u][i].t ;
41
+ inDegree[v]--;
42
+ if (inDegree[v] == 0 ) q.push (v);
43
+ }
44
+ }
45
+
46
+ return cnt == G.size ();
47
+ }
48
+
49
+ void dijkstra () {
50
+ int src = G.size () - 1 ; // G[n] is convergence start point
51
+ vector<int > dis (G.size (), MAXN), vou (G.size (), 0 );
52
+ vector<bool > visited (G.size (), false );
53
+ pre.resize (G.size (), -1 );
54
+ dis[src] = 0 ;
55
+
56
+ priority_queue<pair<int , int >, vector<pair<int , int >>, greater<pair<int , int >>> pq;
57
+ pq.push ({0 , src});
58
+ while (!pq.empty ()) {
59
+ auto e = pq.top (); pq.pop ();
60
+ int s = e.first , u = e.second ;
61
+ visited[u] = true ;
62
+
63
+ if (dis[u] != MAXN && dis[u] < s) continue ;
64
+
65
+ for (int i = 0 ; i < G[u].size (); i++) {
66
+ Node v = G[u][i];
67
+ if (visited[v.t ]) continue ;
68
+ if (dis[u] + v.s < dis[v.t ]) {
69
+ dis[v.t ] = dis[u] + v.s ;
70
+ vou[v.t ] = vou[u] + v.d ;
71
+ pre[v.t ] = u;
72
+ pq.push ({dis[v.t ], v.t });
73
+ } else if (dis[u] + v.s == dis[v.t ] && vou[u] + v.d > vou[v.t ]) {
74
+ vou[v.t ] = vou[u] + v.d ;
75
+ pre[v.t ] = u;
76
+ pq.push ({dis[v.t ], v.t });
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ void print (int t) {
83
+ int src = G.size () - 1 ; // G[n] is convergence start point
84
+ if (t == src) return ;
85
+ print (pre[t]);
86
+ if (hasInDegree[t]) cout << " ->" ;
87
+ cout << t;
88
+ }
89
+
90
+
91
+ int main () {
92
+ ios::sync_with_stdio (false );
93
+ int n, m, t;
94
+ cin >> n >> m;
95
+ G.resize (n, vector<Node>());
96
+ hasInDegree.resize (n+1 , false );
97
+ for (int i = 0 ; i < m; i++) {
98
+ Node node = Node ();
99
+ cin >> t >> node.t >> node.s >> node.d ;
100
+ hasInDegree[node.t ] = true ;
101
+ G[t].push_back (node);
102
+ }
103
+
104
+ vector<int > starts;
105
+ for (int i = 0 ; i < n; i++) {
106
+ if (!hasInDegree[i]) starts.push_back (i);
107
+ }
108
+
109
+ bool isValid = isDAG ();
110
+ cout << (isValid ? " Okay." : " Impossible." ) << endl;
111
+
112
+ // add a convergence point G[n] to link all starts
113
+ G.push_back (vector<Node>());
114
+ for (const int &t : starts) {
115
+ Node node = Node ();
116
+ node.t = t;
117
+ node.s = node.d = 0 ;
118
+ G[n].push_back (node);
119
+ }
120
+ dijkstra ();
121
+
122
+ int k;
123
+ cin >> k;
124
+ for (int i = 0 ; i < k; i++) {
125
+ cin >> t;
126
+ if (!hasInDegree[t]) cout << " You may take test " << t << " directly." << endl;
127
+ else if (!isValid) cout << " Error." << endl;
128
+ else { print (t); cout << endl;}
129
+ }
130
+
131
+ return 0 ;
132
+ }
0 commit comments