Let's assume \ (A \ Le B \ Le C \) , note that we will be able from the communication block continuously puncturing point resulting smaller communication block, it is possible to Imperial size \ (A \) and \ (B \) of point set is connected
Because it is size \ (A \) and (B \) \ after the two blocks identified communication, we will inevitably make these two blocks communication expanding these two points set includes all \ (n-\) th point, the problem is converted into the original image into two blocks of communication, a size of at least \ (a \) , a size of at least \ (B \)
In other words, these two blocks selected from any of a communication, which must meet the size \ ([a, nb] \ ) or within \ ([b, na] \ ) inside. Wherein if a condition is satisfied block communication method, wherein a communication block condition is not satisfied is not legitimate
Xianpao again DFS tree, the tree enumerate each side, if this side of the divided blocks satisfy the condition of communication directly output answers
Otherwise, consider the center of gravity of the DFS tree. Noting the size of the center of gravity of each subtree is not in \ ([a, nb] \ ) within (or has been previously determined as valid), and as \ (a + b + c = n \) and \ (a \ le b \ Le C \) , so \ (B \ Le \ FRAC N2 \) , by the nature of the center of gravity (each of them do not exceed the size of the subtrees \ (\ FRAC N2 \) ) to obtain the center of gravity of each subtree sizes are \ (<a \)
Consider the center of gravity of each sub-tree. If a child within the tree is not connected to the center of gravity of the ancestors (not including the center of gravity itself) atavistic side, then the sub-tree inevitable and center of gravity belong to the same communication block (this would certainly not make the tree subtree where the communication block size \ (\ ge a \) )
All such sub tree and a communication block synthesis of gravity, if the block is larger than the size of the communication \ (Na \) no solution
Otherwise, a configuration of the initial solution, the center of gravity on the sub-tree \ (B \) set, the rest is placed \ (A \) set
Obviously, the size of the center of gravity of the sub-tree is more than \ (na \) is (because the center of gravity above that lump size \ (<A \) )
All have in turn connected to the return side of the center of gravity ancestral progenitor subtree move the center of gravity \ (A \) within the set, until the \ (B \) size of the set \ (\ le na \) up
How to prove this to get a \ (B \) collection size \ (\ GE b \) ?
Proof: From each \ (B \) delete the collection of a certain subtree size \ (<A \) , and \ (a \ le b \ le c \) ensures \ (a \ le \ frac n3 \) and \ (C \ GE \ FRAC N3 \) , and the interval \ ([b, na] \ ) is the size of \ (C +. 1 \) , so \ (a \) must be smaller than the interval \ ([b, na] \) size, which means that \ (B \) collection size \ (> na \) in the case of, no matter which sub-tree once deleted will not let \ (B \) collection size becomes \ (<b \) , is proved
\(O(n+m)\)
Code
#include <bits/stdc++.h>
template <class T>
inline void read(T &res)
{
res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
if (bo) res = ~res + 1;
}
template <class T>
inline T Max(const T &a, const T &b) {return a > b ? a : b;}
template <class T>
inline T Min(const T &a, const T &b) {return a < b ? a : b;}
const int N = 1e5 + 5, M = 4e5 + 5;
int n, m, a, b, c, ecnt, nxt[M], adj[N], sze[N], maxs[N], go[M], tr[4],
dep[N], ans[N], G = 1;
bool vis[N], ind[N];
std::vector<int> son[N];
void add_edge(int u, int v)
{
nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v;
nxt[++ecnt] = adj[v]; adj[v] = ecnt; go[ecnt] = u;
}
void dfs(int u)
{
vis[u] = 1; sze[u] = 1;
for (int e = adj[u], v; e; e = nxt[e])
if (!vis[v = go[e]])
{
dep[v] = dep[u] + 1; dfs(v); sze[u] += sze[v];
maxs[u] = Max(maxs[u], sze[v]);
son[u].push_back(v);
}
}
int calc(int u)
{
int res = n + 1;
for (int e = adj[u], v = go[e]; e; e = nxt[e], v = go[e])
res = Min(res, dep[v]);
for (int i = 0; i < son[u].size(); i++)
res = Min(res, calc(son[u][i]));
return res;
}
void setr(int u, int c)
{
ans[u] = c;
for (int i = 0; i < son[u].size(); i++)
setr(son[u][i], c);
}
void other(int c)
{
for (int u = 1; u <= n; u++) if (!ans[u]) ans[u] = c;
}
void fake(int u, int s)
{
vis[u] = 1; sze[u] = 1;
for (int e = adj[u], v; e; e = nxt[e])
if (!vis[v = go[e]] && ans[u] == ans[v])
{
fake(v, s); sze[u] += sze[v];
if (s <= sze[v]) return;
s -= sze[v];
}
if (s) ans[u] = 3;
}
void output(int ca, int cb)
{
memset(vis, 0, sizeof(vis));
for (int u = 1; u <= n; u++)
if (ans[u] == 1) {fake(u, ca - a); break;}
for (int u = 1; u <= n; u++)
if (ans[u] == 2) {fake(u, cb - b); break;}
for (int u = 1; u <= n; u++) printf("%d ", tr[ans[u]]);
puts(""); exit(0);
}
int main()
{
int x, y;
read(n); read(m); read(a); read(b); read(c);
tr[1] = 1; tr[2] = 2; tr[3] = 3;
if (a > b) std::swap(a, b), std::swap(tr[1], tr[2]);
if (a > c) std::swap(a, c), std::swap(tr[1], tr[3]);
if (b > c) std::swap(b, c), std::swap(tr[2], tr[3]);
while (m--) read(x), read(y), add_edge(x + 1, y + 1);
dfs(dep[1] = 1);
for (int u = 2; u <= n; u++)
{
if (a <= sze[u] && sze[u] <= n - b)
setr(u, 1), other(2), output(sze[u], n - sze[u]);
if (b <= sze[u] && sze[u] <= n - a)
setr(u, 2), other(1), output(n - sze[u], sze[u]);
}
for (int u = 2; u <= n; u++)
if (Max(maxs[u], n - sze[u]) < Max(maxs[G], n - sze[G]))
G = u;
int sum = 1;
for (int i = 0; i < son[G].size(); i++)
if (ind[i] = calc(son[G][i]) >= dep[G]) sum += sze[son[G][i]];
if (sum > n - a) output(0, 0);
setr(G, 2); other(1); sum = sze[G];
for (int i = 0; i < son[G].size(); i++)
if (!ind[i] && sum > n - a) sum -= sze[son[G][i]], setr(son[G][i], 1);
return output(n - sum, sum), 0;
}