tarjan condensing point cutpoint

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();}

 

Guess you like

Origin www.cnblogs.com/chiarochinoful/p/algorithm-tarjan.html