Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<iostream>
- #include<vector>
- #include<string>
- #include<algorithm>
- #include<cstdio>
- #include<numeric>
- #include<cstring>
- #include<ctime>
- #include<cstdlib>
- #include<set>
- #include<map>
- #include<unordered_map>
- #include<unordered_set>
- #include<list>
- #include<cmath>
- #include<bitset>
- #include<cassert>
- using namespace std;
- typedef vector<int> vi;
- const int N = 1009;
- const int inf = (int) 2e9;
- const int MAXN = 1000, LOGMAXN = 20;
- const int INF = 1000 * 1000 * 1000 + 7;
- #define PB push_back
- #define SZ(s) (int) s.size ()
- struct test
- {
- int n, m;
- vector<pair<int, int> >edges;
- vector<pair<int, int> >queries;
- };
- struct stupid
- {
- int n;
- int m;
- int l;
- int cnt;
- int timer;
- int tin[N];
- int tout[N];
- int dist[N];
- int up[N][50];
- int u[N];
- int sz[N];
- int par[N];
- int ans[N];
- vi g[N];
- vi d[N];
- stupid()
- {
- n = 0;
- m = 0;
- l = 0;
- cnt = 0;
- timer = 0;
- for (int i = 0; i < N; i++)
- {
- tin[i] = 0;
- tout[i] = 0;
- dist[i] = 0;
- for (int j = 0; j < 50; j++)
- {
- up[i][j] = 0;
- }
- u[i] = 0;
- sz[i] = 0;
- par[i] = 0;
- ans[i] = 0;
- g[i] = vector<int>();
- d[i] = vector<int>();
- }
- }
- void dfs0(int v, int p = 0) {
- tin[v] = timer++;
- up[v][0] = p;
- for (int i = 1; i <= l; i++) {
- up[v][i] = up[up[v][i - 1]][i - 1];
- }
- for (int i = 0; i < SZ(g[v]); i++) {
- int to = g[v][i];
- if (to != p) {
- dist[to] = dist[v] + 1;
- dfs0(to, v);
- }
- }
- tout[v] = timer++;
- }
- void dfs1(int v, int p = -1) {
- cnt++;
- sz[v] = 1;
- for (int i = 0; i < SZ(g[v]); i++) {
- int to = g[v][i];
- if (to == p || u[to]) {
- continue;
- }
- else {
- dfs1(to, v);
- sz[v] += sz[to];
- }
- }
- }
- int dfs2(int v, int p = -1) {
- int mx = cnt - sz[v];
- for (int i = 0; i < SZ(g[v]); i++) {
- int to = g[v][i];
- if (!u[to] && to != p) {
- mx = max(mx, sz[to]);
- }
- }
- if (mx <= cnt / 2) {
- return v;
- }
- else {
- for (int i = 0; i < SZ(g[v]); i++) {
- int to = g[v][i];
- if (to == p || u[to]) {
- continue;
- }
- else {
- int res = dfs2(to, v);
- if (res != -1) {
- return res;
- }
- }
- }
- }
- return -1;
- }
- void dfs3(int v) {
- for (int i = 0; i < SZ(d[v]); i++) {
- int to = d[v][i];
- if (to != par[v]) {
- par[to] = v;
- dfs3(to);
- }
- }
- }
- int decompose(int v) {
- cnt = 0;
- dfs1(v);
- int c = dfs2(v);
- u[c] = 1;
- for (int i = 0; i < SZ(g[c]); i++) {
- int to = g[c][i];
- if (!u[to]) {
- to = decompose(to);
- d[c].PB(to);
- d[to].PB(c);
- }
- }
- return c;
- }
- bool upper(int a, int b) {
- return tin[a] <= tin[b] && tout[b] <= tout[a];
- }
- int lca(int a, int b) {
- if (upper(a, b)) {
- return a;
- }
- else if (upper(b, a)) {
- return b;
- }
- else {
- for (int i = l; i >= 0; i--) {
- if (!upper(up[a][i], b)) {
- a = up[a][i];
- }
- }
- return up[a][0];
- }
- }
- int f(int a, int b) {
- return dist[a] + dist[b] - 2 * dist[lca(a, b)];
- }
- void update(int v) {
- int u = v;
- while (v != -1) {
- ans[v] = min(ans[v], f(u, v));
- v = par[v];
- }
- }
- int get(int v) {
- int u = v;
- int res = inf;
- while (v != -1) {
- res = min(res, ans[v] + f(u, v));
- v = par[v];
- }
- return res;
- }
- vector<int>solve(test t)
- {
- n = t.n;
- m = t.m;
- for (int i = 0; i < n - 1; i++) {
- int a, b;
- a = t.edges[i].first;
- b = t.edges[i].second;
- g[a].PB(b);
- g[b].PB(a);
- }
- while ((1 << l) <= n) {
- l++;
- }
- dfs0(1);
- int c = decompose(1);
- for (int i = 1; i <= n; i++) {
- par[i] = -1;
- ans[i] = inf;
- }
- dfs3(c);
- for (int i = 1; i <= n; i++) {
- if (i != c) {
- assert(par[i] != -1);
- }
- }
- update(1);
- vector<int>res;
- for (int i = 0; i < m; i++)
- {
- int x, v;
- x = t.queries[i].first;
- v = t.queries[i].second;
- if (x == 1) {
- update(v);
- }
- else {
- res.push_back(get(v));
- }
- }
- return res;
- }
- };
- struct smart
- {
- vector<int>tree[MAXN];
- int height[MAXN], timeIn[MAXN], timeOut[MAXN];
- int ancestor[MAXN][LOGMAXN];
- bool used[MAXN];
- bool used2[MAXN];
- bool wasCentroid[MAXN];
- int subtreeSize[MAXN];
- int decompositionParent[MAXN];
- int bestLen[MAXN], bestPos[MAXN];
- int dfsTimer = 1;
- smart()
- {
- for (int i = 0; i < MAXN; i++)
- {
- tree[i] = vector<int>();
- height[i] = 0;
- timeIn[i] = 0;
- timeOut[i] = 0;
- for (int j = 0; j < LOGMAXN; j++)
- {
- ancestor[i][j] = 0;
- }
- used[i] = false;
- used2[i] = false;
- wasCentroid[i] = false;
- subtreeSize[i] = 0;
- decompositionParent[i] = 0;
- bestLen[i] = 0;
- bestPos[i] = 0;
- }
- }
- void clearFull(int n)
- {
- for (int i = 1; i <= n; i++)
- {
- used[i] = false;
- used2[i] = false;
- subtreeSize[i] = 0;
- }
- }
- void precalcLCA(int v, int parent = 1, int curHeight = 1)
- {
- used[v] = true;
- timeIn[v] = dfsTimer;
- dfsTimer++;
- ancestor[v][0] = parent;
- height[v] = curHeight;
- for (int i = 1; i < LOGMAXN; i++)
- {
- ancestor[v][i] = ancestor[ancestor[v][i - 1]][i - 1];
- }
- for (int i = 0; i < tree[v].size(); i++)
- {
- int to = tree[v][i];
- if (!used[to])
- {
- precalcLCA(to, v, curHeight + 1);
- }
- }
- timeOut[v] = dfsTimer;
- dfsTimer++;
- }
- bool isAncestor(int u, int v)
- {
- return timeIn[u] <= timeIn[v] && timeOut[u] >= timeOut[v];
- }
- int LCA(int u, int v)
- {
- for (int i = LOGMAXN - 1; i >= 0; i--)
- {
- if (!isAncestor(ancestor[u][i], v))
- {
- u = ancestor[u][i];
- }
- }
- return ancestor[u][0];
- }
- int verticalPathLength(int u, int v)
- {
- return height[v] - height[u];
- }
- int pathLength(int u, int v)
- {
- if (isAncestor(u, v))
- {
- return verticalPathLength(u, v);
- }
- else if (isAncestor(v, u))
- {
- return verticalPathLength(v, u);
- }
- else
- {
- int lca = LCA(u, v);
- return verticalPathLength(lca, u) + verticalPathLength(lca, v);
- }
- }
- void calcSizes(int v)
- {
- used[v] = true;
- subtreeSize[v] = 1;
- for (int i = 0; i < tree[v].size(); i++)
- {
- int to = tree[v][i];
- if (!used[to] && !wasCentroid[to])
- {
- calcSizes(to);
- subtreeSize[v] += subtreeSize[to];
- }
- }
- }
- int findCentroid(int v, int rootSize = -1, int upSize = 0)
- {
- used2[v] = true;
- if (rootSize == -1)
- {
- rootSize = (subtreeSize[v] + 1) / 2;
- }
- int ans = -1;
- bool isCentroid = true;
- if (upSize > rootSize) isCentroid = false;
- for (int i = 0; i < tree[v].size(); i++)
- {
- int to = tree[v][i];
- if (!used2[to] && !wasCentroid[to] && subtreeSize[to] > rootSize) isCentroid = false;
- }
- if (isCentroid)
- {
- ans = v;
- }
- for (int i = 0; i < tree[v].size(); i++)
- {
- int to = tree[v][i];
- if (!used2[to] && !wasCentroid[to])
- {
- int tmp = findCentroid(to, rootSize, upSize + subtreeSize[v] - subtreeSize[to]);
- if (tmp != -1)
- {
- ans = tmp;
- }
- }
- }
- return ans;
- }
- void color(int v)
- {
- int u = v;
- while (u != -1)
- {
- int curLen = pathLength(u, v);
- if (curLen < bestLen[u])
- {
- bestLen[u] = curLen;
- bestPos[u] = v;
- }
- u = decompositionParent[u];
- }
- }
- int findNearest(int v)
- {
- int u = v;
- int ans = INF;
- while (u != -1)
- {
- if (bestPos[u] != -1)
- {
- ans = min(ans, pathLength(bestPos[u], v));
- }
- u = decompositionParent[u];
- }
- return ans;
- }
- vector<int>solve(test t)
- {
- // freopen("input.txt", "r", stdin);
- // freopen("output.txt", "w", stdout);
- int n, m;
- n = t.n;
- m = t.m;
- for (int i = 0; i < n - 1; i++)
- {
- int u, v;
- //scanf("%d%d", &u, &v);
- //u = i;
- //v = i + 1;
- u = t.edges[i].first;
- v = t.edges[i].second;
- tree[u].push_back(v);
- tree[v].push_back(u);
- }
- precalcLCA(1);
- clearFull(n);
- calcSizes(1);
- int decompositionRoot = findCentroid(1);
- decompositionParent[decompositionRoot] = -1;
- wasCentroid[decompositionRoot] = true;
- vector<int>lastLayer;
- lastLayer.push_back(decompositionRoot);
- int lcnt = 0;
- while (!lastLayer.empty())
- {
- lcnt++;
- assert(lcnt < 40);
- clearFull(n);
- vector<int>newCentroids;
- for (int i = 0; i < lastLayer.size(); i++)
- {
- int v = lastLayer[i];
- for (int j = 0; j < tree[v].size(); j++)
- {
- int to = tree[v][j];
- if (!wasCentroid[to] && !used[to])
- {
- calcSizes(to);
- int curCenter = findCentroid(to);
- decompositionParent[curCenter] = v;
- wasCentroid[curCenter] = true;
- newCentroids.push_back(curCenter);
- }
- }
- }
- lastLayer = newCentroids;
- }
- for (int i = 1; i <= n; i++)
- {
- bestLen[i] = INF;
- bestPos[i] = -1;
- }
- color(1);
- vector<int>res;
- for (int i = 0; i < m; i++)
- {
- int type;
- //scanf("%d", &type);
- type = t.queries[i].first;
- if (type == 1)
- {
- int v;
- v = t.queries[i].second;
- color(v);
- }
- else
- {
- int v;
- v = t.queries[i].second;
- res.push_back(findNearest(v));
- }
- }
- return res;
- }
- };
- test gen(int n, int m)
- {
- test ans;
- ans.n = n;
- ans.m = m;
- for (int i = 2; i <= n; i++)
- {
- ans.edges.push_back(make_pair(rand() % (i - 1) + 1, i));
- }
- for (int i = 0; i < m; i++)
- {
- ans.queries.push_back(make_pair(rand() % 2 + 1, rand() % n + 1));
- }
- return ans;
- }
- int main()
- {
- int cnt = 0;
- freopen("output.txt", "w", stdout);
- while (1)
- {
- test t = gen(10, 10);
- stupid st = stupid();
- smart sm = smart();
- vector<int>ans1 = st.solve(t);
- vector<int>ans2 = sm.solve(t);
- bool ok = true;
- if (ans1.size() != ans2.size())
- {
- ok = false;
- }
- for (int i = 0; i < ans1.size(); i++)
- {
- if (ans1[i] != ans2[i])
- {
- ok = false;
- }
- }
- if (!ok)
- {
- printf("%d %d\n", t.n, t.m);
- for (int i = 0; i < t.n - 1; i++)
- {
- printf("%d %d\n", t.edges[i].first, t.edges[i].second);
- }
- for (int i = 0; i < t.m; i++)
- {
- printf("%d %d\n", t.queries[i].first, t.queries[i].second);
- }
- return 0;
- }
- cnt++;
- cerr << cnt << " Tests passed" << endl;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement