Tarjan + DAG上跑PD
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cctype> 6 #include <cstdio> 7 8 using namespace std; 9 10 inline void read(int &x) 11 { 12 int k = 1; x = 0; 13 char ch = getchar(); 14 while (!isdigit(ch)) 15 if (ch == '-') ch = getchar(), k = -1; 16 else ch = getchar(); 17 while (isdigit(ch)) 18 x = (x << 1) + (x << 3) + (ch ^ 48), 19 ch = getchar(); 20 x *= k; 21 } 22 23 const int N = 101010; 24 int n, cnt = 0, x, top, color = 0, tag = 0, cur, cnt2 = 0; 25 int f[N], v[N], dfn[N], low[N], stk[N], col[N], F[N], in[N], sum[N], ans[N]; 26 27 struct Edge 28 { 29 int u, v, nxt; 30 }e[N << 2], E[N << 2]; 31 32 inline void Addedge(int a, int b) 33 { 34 ++cnt; 35 e[cnt].u = a; 36 e[cnt].v = b; 37 e[cnt].nxt = f[a]; 38 f[a] = cnt; 39 } 40 41 inline void addedge(int a, int b) 42 { 43 ++cnt2; 44 E[cnt2].u = a; 45 E[cnt2].v = b; 46 E[cnt2].nxt = F[a]; 47 F[a] = cnt2; 48 } 49 50 void Tarjan(int u) 51 { 52 dfn[u] = low[u] = ++tag; 53 stk[++top] = u; v[u] = 1; 54 for (int i = f[u]; i != -1; i = e[i].nxt) 55 if (!dfn[e[i].v]) 56 Tarjan(e[i].v), low[u] = min(low[u], low[e[i].v]); 57 else if (v[e[i].v]) 58 low[u] = min(low[u], low[e[i].v]); 59 if (dfn[u] == low[u]) 60 { 61 ++color; 62 do 63 { 64 cur = stk[top--]; 65 col[cur] = color; 66 ++sum[color]; 67 v[cur] = 0; 68 }while (cur != u); 69 } 70 } 71 72 void DFS(int u) 73 { 74 for (int i = F[u]; i != -1; i = E[i].nxt) 75 ans[E[i].v] += ans[u], DFS(E[i].v); 76 } 77 78 int main() 79 { 80 read(n); 81 memset(f, -1, sizeof(f)); 82 memset(F, -1, sizeof(F)); 83 for (int i = 1; i <= n; ++i) { read(x); if (i != x) Addedge(i, x); } 84 for (int i = 1; i <= n; ++i) if (!dfn[i]) Tarjan(i); 85 for (int i = 1; i <= cnt; ++i) 86 if (col[e[i].v] != col[e[i].u]) 87 addedge(col[e[i].v], col[e[i].u]), ++in[col[e[i].u]]; 88 for (int i = 1; i <= color; ++i) ans[i] = sum[i]; 89 for (int i = 1; i <= color; ++i) if (!in[i]) DFS(i); 90 for (int i = 1; i <= n; ++i) printf("%d ", ans[col[i]]); 91 return 0; 92 }