1 条题解
-
0
假设原图不存在孤点。
权值为 的点一定是 号或 号,否则一定有至少一个与其相邻的点权值比 更小,但这显然不可能。
权值为 的点同理。
我们钦定 ,。如果存在一组解中 ,那么将所有 变为 即可调整得 。
假设解存在。那么可以在图上,按照 的大小顺序遍历每个点。设当前遍历到 号点,其度数为 ,那么在与 相邻的点中,一定有恰好 个点被遍历过,它们的权值 ;剩下恰好 个点没有被遍历过,它们的权值 。
这启发我们用一个类似拓扑排序的过程来求出一组 。维护一个队列。初始时,将所有与 号相邻并且度数恰为 的点加入队列。对于第 个出队的点 ,令 ,然后将其从图中删掉。访问所有删掉 之前与 相邻的点 ,设删除 后 的度数为 ,若 ,这意味着 已经有恰好 个相邻的点被遍历过,这时可以将 加入队列。
如果这样的遍历不能完全进行,即除了 号和 号以外,还有点没有入过队,那么无解;如果 出队时,,这不满足遍历 时恰有 个相邻点被遍历过,也无解。
若原图存在孤点,它们的权值也可以为 或 ,但这并不影响。给他们随便赋几个值,剩下的部分是一样的。
时间复杂度 ,实现有一些细节。
#include <bits/stdc++.h> #define F(i, a, b) for(int i = (a); i <= (b); ++i) #define dF(i, a, b) for(int i = (a); i >= (b); --i) using namespace std; typedef long long LL; typedef unsigned long long ull; typedef unsigned int uint; typedef pair<int, LL> pii; const int N = 5e5 + 5; int n, m, deg[N], h[N]; vector<int> e[N]; int main() { // freopen("zyq.in", "r", stdin); // freopen("zyq.out", "w", stdout); ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); cin >> n >> m; F(i, 1, m) { int u, v; cin >> u >> v; e[u].push_back(v), e[v].push_back(u); ++deg[u], ++deg[v]; } F(i, 3, n) deg[i] >>= 1; h[1] = 1, h[2] = n; queue<int> q; int now = 1; F(i, 3, n) if (!deg[i]) h[i] = ++now; for (auto v : e[1]) --deg[v]; F(i, 3, n) if (!h[i] && !deg[i]) q.push(i); while (!q.empty()) { int u = q.front(); q.pop(), h[u] = ++now; if (deg[u]) return cout << "NIE\n", 0; for (auto v : e[u]) if (!h[v] && !(--deg[v])) q.push(v); } if (now < n - 1) return cout << "NIE\n", 0; cout << "TAK\n"; F(i, 1, n) cout << h[i] << " "; return 0; }
- 1
信息
- ID
- 7536
- 时间
- 5000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者