1. 程式人生 > >BZOJ 3331 [BeiJing2013]壓力-Tarjan + 樹上差分

BZOJ 3331 [BeiJing2013]壓力-Tarjan + 樹上差分

getchar jin ace flag g++ 註意 edge fine bzoj

Solution

Tarjan 點雙縮點, 加上樹上差分計算。

註意特判。。。 我特判掛了好久嗚嗚嗚

Code

技術分享圖片
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #define rd read()
  6 using namespace std;
  7 
  8 const int N = 1e5 + 5;
  9 const int M = 2e5 + 5;
 10 const
int base = 30; 11 12 int head[N], tot; 13 int Head[N << 1], Tot; 14 int low[N], dfn[N], cnt, col, c[N], cut[N], n, m, Q; 15 int f[N << 2][30], nd, id[N], idf[N << 2], dep[N << 2]; 16 int st[N], tp, num[N], sum[N << 2]; 17 18 vector<int> q[N << 1
]; 19 20 struct edge { 21 int nxt, to; 22 }e[M << 1], E[M << 3]; 23 24 int read() { 25 int X = 0, p = 1; char c = getchar(); 26 for (; c > 9 || c < 0; c = getchar()) if (c == -) p = -1; 27 for (; c >= 0 && c <= 9; c = getchar()) X = X * 10
+ c - 0; 28 return X * p; 29 } 30 31 void add(int u, int v) { 32 e[++tot].to = v; 33 e[tot].nxt = head[u]; 34 head[u] = tot; 35 } 36 37 void Add(int u, int v) { 38 E[++Tot].to = v; 39 E[Tot].nxt = Head[u]; 40 Head[u] = Tot; 41 } 42 43 void tarjan(int u) { 44 low[u] = dfn[u] = ++cnt; 45 st[++tp] = u; 46 int flag = 0; 47 for (int i = head[u]; i; i = e[i].nxt) { 48 int nt = e[i].to; 49 if (!dfn[nt]) { 50 tarjan(nt); 51 low[u] = min(low[u], low[nt]); 52 if (low[nt] >= dfn[u]) { 53 flag++; 54 if (flag > 1 || u - 1) 55 cut[u] = 1; 56 col++; 57 for (; tp;) { 58 int v = st[tp--]; 59 q[col].push_back(v); 60 if (v == nt) 61 break; 62 } 63 q[col].push_back(u); 64 } 65 } 66 else low[u] = min(low[u], dfn[nt]); 67 } 68 } 69 70 void dfs(int u) { 71 for (int i = Head[u]; i; i = E[i].nxt) { 72 int nt = E[i].to; 73 if (f[u][0] == nt) 74 continue; 75 f[nt][0] = u; 76 dep[nt] = dep[u] + 1; 77 dfs(nt); 78 } 79 } 80 81 int LCA(int x, int y) { 82 if (dep[x] < dep[y]) 83 swap(x, y); 84 for (int k = base - 1; ~k; --k) 85 if (dep[f[x][k]] >= dep[y]) 86 x = f[x][k]; 87 if (x == y) 88 return x; 89 for (int k = base - 1; ~k; --k) 90 if (f[x][k] != f[y][k]) 91 x = f[x][k], y = f[y][k]; 92 return f[x][0]; 93 } 94 95 void dfs2(int u) { 96 for (int i = Head[u]; i; i = E[i].nxt) { 97 int nt = E[i].to; 98 if (nt == f[u][0]) 99 continue; 100 dfs2(nt); 101 sum[u] += sum[nt]; 102 } 103 if(u > col) 104 num[idf[u]] += sum[u]; 105 } 106 107 int main() 108 { 109 //freopen("1.in","r", stdin); 110 //freopen("out.out","w",stdout); 111 n = rd; m = rd; Q = rd; 112 for (int i = 1; i <= m; ++i) { 113 int u = rd, v = rd; 114 add(u, v); add(v, u); 115 } 116 tarjan(1); 117 nd = col; 118 for (int i = 1; i <= n; ++i) 119 if (cut[i]) c[i] = ++nd, idf[nd] = i; 120 for (int i = 1; i <= col; ++i) 121 for(int j = 0, len = q[i].size(); j < len; ++j) { 122 int x = q[i][j]; 123 if (cut[x]) 124 Add(i, c[x]), Add(c[x], i); 125 else c[x] = i; 126 } 127 dep[1] = 1; 128 dfs(1); 129 for (int k = 1; k < base; ++k) 130 for (int i = 1; i <= nd; ++i) 131 f[i][k] = f[f[i][k - 1]][k - 1]; 132 for (; Q; Q--) { 133 int u = rd, v = rd, lca; 134 if (c[u] <= col) num[u]++; 135 if (c[v] <= col) num[v]++; 136 u = c[u]; v = c[v]; 137 if (u == v) continue; 138 lca = LCA(u, v); 139 sum[v]++; sum[u]++; 140 sum[lca]--; sum[f[lca][0]]--; 141 } 142 dfs2(1); 143 for (int i = 1; i <= n; ++i) 144 printf("%d\n", num[i]); 145 }
View Code

BZOJ 3331 [BeiJing2013]壓力-Tarjan + 樹上差分