Tarjan algorithm
First time nonsense: very ashamed to say, several months before the school had tarjan algorithm but now for the first time to write
Template title: [luogu P3387] [template] point reduction
tarjan condensing point & dp
The obvious answer to why shrink point
A ring shrunk to the point
Then the topology of FIG dp
tarjan algorithm has a lot of the same name, such as this blog shrink algorithm point tarjan cut point of fact, not a thing, but it is similar
This tarjan, need three things
First: a stack to store the search to the point
Second: a timestamp dfn, represents the first of several searches to this point
Third: low array, represents the first sequence number in the stack be traced to a node
First, there must be initialized when
1 dfn[now] = low[now] = ++Index
Then start traversing edge
If you have not touched traverse to the point
Then recursively tarjan
After the recursion
1 low[now] = std::min(low[now], low[to]);
So if the next point has been to na
Then do not recursion
1 low[now] = std::min(low[now], dfn[to]);
Why is dfn it?
According to my understanding, it should be if the direct use of low maybe will jump to this place outside the ring
But this point tarjan shrink inside the dfn into low is possible, but a cut point tarjan will not be able to
When a low point last time == dfn, that this point is bound to be reduced after a point still remains in a point on the map
Then it can be quickly reduced down point, the stop element of the stack outwardly elastic grindstone
Then according to the nature of the topic topology dp, gone
1 #include<cmath> 2 #include<queue> 3 #include<stack> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<iostream> 8 #include<algorithm> 9 #define APART puts("----------------------") 10 #define debug 1 11 #define FILETEST 0 12 #define inf 100010 13 #define ll long long 14 #define ha 998244353 15 #define INF 0x7fffffff 16 #define INF_T 9223372036854775807 17 #define DEBUG printf("%s %d\n",__FUNCTION__,__LINE__) 18 19 namespace chino{ 20 21 inline void setting(){ 22 #if FILETEST 23 freopen("test.in", "r", stdin); 24 freopen("test.me.out", "w", stdout); 25 #endif 26 return; 27 } 28 29 inline int read(){ 30 char c = getchar(), up = c; int num = 0; 31 for(; c < '0' || c > '9'; up = c, c = getchar()); 32 for(; c >= '0' && c <= '9'; num = (num << 3) + (num << 1) + (c ^ '0'), c = getchar()); 33 return up == '-' ? -num : num; 34 } 35 36 int n, m; 37 int ans; 38 int cntE, cntR, cntJ; 39 int val[inf], dp[inf]; 40 int vis[inf], in[inf]; 41 int belong[inf], dfn[inf], low[inf]; 42 int head[inf], rehead[inf]; 43 struct Edge{ 44 int to; 45 int from; 46 int next; 47 }e[inf << 1], r[inf << 1]; 48 std::queue <int> Q; 49 std::stack <int> S; 50 51 inline void AddEdge(int from, int to, int &cntE, int *head, Edge *e){ 52 ++cntE; 53 e[cntE].from = from; 54 e[cntE].to = to; 55 e[cntE].next = head[from]; 56 head[from] = cntE; 57 return; 58 } 59 60 void tarjan(int now){ 61 low[now] = dfn[now] = ++cntJ; 62 vis[now] = 1; 63 S.push(now); 64 for(int i = head[now]; i; i = e[i].next){ 65 int to = e[i].to; 66 if(dfn[to] == 0){ 67 tarjan(to); 68 low[now] = std::min(low[now], low[to]); 69 } else if(vis[to]) 70 low[now] = std::min(low[now], dfn[to]); 71 } 72 if(low[now] == dfn[now]){ 73 int top = S.top(); 74 while(1){ 75 top = S.top(); 76 S.pop(); 77 belong[top] = now; 78 vis[top] = 0; 79 if(top == now) 80 break; 81 val[now] += val[top]; 82 } 83 } 84 return; 85 } 86 87 inline void topoDP(){ 88 while(!Q.empty()) 89 Q.pop(); 90 for(int i = 1; i <= n; i++){ 91 if(belong[i] == i && in[i] == 0) 92 Q.push(i), dp[i] = val[i]; 93 } 94 while(!Q.empty()){ 95 int x = Q.front(); 96 Q.pop(); 97 for(int i = rehead[x]; i; i = r[i].next){ 98 int to = r[i].to; 99 dp[to] = std::max(dp[to], dp[x] + val[to]); 100 --in[to]; 101 if(in[to] == 0) 102 Q.push(to); 103 } 104 } 105 return; 106 } 107 108 inline int main(){ 109 n = read(); 110 m = read(); 111 for(int i = 1; i <= n; i++) 112 val[i] = read(); 113 for(int i = 1; i <= m; i++){ 114 int u = read(); 115 int v = read(); 116 AddEdge(u, v, cntE, head, e); 117 } 118 for(int i = 1; i <= n; i++){ 119 if(dfn[i] == 0) 120 tarjan(i); 121 } 122 for(int i = 1; i <= m; i++){ 123 int u = belong[e[i].from]; 124 int v = belong[e[i].to]; 125 if(u == v) 126 continue; 127 AddEdge(u, v, cntR, rehead, r); 128 ++in[v]; 129 } 130 topoDP(); 131 for(int i = 1; i <= n; i++) 132 ans = std::max(ans, dp[i]); 133 printf("%d\n", ans); 134 return 0; 135 } 136 137 }//namespace chino 138 139 int main(){return chino::main();}