[Luogu 2169] Regular Expression
<题目链接>
Thanks for question 0 x is.
I have never written a question in my memory for a long time...
Don't be fooled by the question name! This is not a regular expression question! It has nothing to do with character (string) processing! This is a graphic topic. Hello!
I'm not in a hurry. Capella, what are you in a hurry?
According to the question, the machines that can be locally transmitted are in the same strongly connected component, so Tarjan times and shrinks. In the process of contraction, select the short addition for the side between two SCC.
Here I use a map to record the ing from edge (pair <int, int>) to edge weight (INT), and then use map to determine whether to add edge.
The shortest path is short. Run a Dijkstra command (cherish your life and stay away from a dead Algorithm without explanation ).
Output the path from the SCC of 1 to the SCC of N.
#include <algorithm>#include <cstdio>#include <cstring>#include <map>#include <queue>#include <stack>#define nullptr NULLconst int MAXN = 200010; int n, m; namespace SCC{ bool exist[MAXN], vis[MAXN]; int num, sum, DFN[MAXN], low[MAXN], SCC[MAXN], dist[MAXN]; std :: stack<int> S; struct Node { int index, dist; Node(int index, int dist): index(index), dist(dist) {} bool operator <(const Node& rhs) const { return dist > rhs.dist; } }; struct Graph { struct Edge { int to, w; Edge *next; Edge(int to, int w, Edge* next): to(to), w(w), next(next) {} ~Edge(void) { if(next != nullptr) delete next; } }*head[MAXN]; Graph(int n) { std :: fill(head + 1, head + n + 1, (Edge*)nullptr); } ~Graph(void) { for(int i = 1; i <= n; ++i) delete head[i]; } void AddEdge(int u, int v, int w) { head[u] = new Edge(v, w, head[u]); } }*G, *Gnew; void Tarjan(int u) { S.push(u); exist[u] = true; DFN[u] = low[u] = ++num; int v; for(Graph :: Edge *i = G -> head[u]; i != nullptr; i = i -> next) if(!DFN[v = i -> to]) { Tarjan(v); low[u] = std :: min(low[u], low[v]); } else if(exist[v]) low[u] = std :: min(low[u], DFN[v]); if(DFN[u] == low[u]) { ++sum; do { exist[v = S.top()] = false; S.pop(); SCC[v] = sum; } while(u ^ v); } } void Shrink(void) { std :: map<std :: pair<int, int>, int> QAQ; std :: pair<int, int> t; Gnew = new Graph(sum); for(int u = 1, v; u <= n; ++u) for(Graph :: Edge *i = G -> head[u]; i != nullptr; i = i -> next) if(!QAQ.count(t = std :: make_pair(SCC[u], SCC[v = i -> to])) || i -> w < QAQ[t]) { Gnew -> AddEdge(SCC[u], SCC[v], i -> w); QAQ[t] = i -> w; } } void Dijkstra(int S) { std :: priority_queue<Node> Q; memset(dist, 0x3f, sizeof dist); Q.push(Node(S, dist[S] = 0)); while(!Q.empty()) { int u = Q.top().index, v; Q.pop(); if(!vis[u]) { vis[u] = true; for(Graph :: Edge *i = Gnew -> head[u]; i != nullptr; i = i -> next) if(dist[v = i -> to] > dist[u] + i -> w) Q.push(Node(v, dist[v] = dist[u] + i -> w)); } } } void Solve(void) { for(int i = 1; i <= n; ++i) if(!DFN[i]) Tarjan(i); Shrink(); Dijkstra(SCC[1]); printf("%d\n", dist[SCC[n]]); }}int main(void){ scanf("%d %d", &n, &m); SCC :: G = new SCC :: Graph(n); for(int i = 1, u, v, w; i <= m; ++i) { scanf("%d %d %d", &u, &v, &w); SCC :: G -> AddEdge(u, v, w); } SCC :: Solve(); return 0; }
Thank you for reading.
[Luogu 2169] Regular Expression