专栏文章
P7966 题解
P7966题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @min1qag5
- 此快照首次捕获于
- 2025/12/01 19:08 3 个月前
- 此快照最后确认于
- 2025/12/01 19:08 3 个月前
首先每条边都要被选入一棵树中。
注意到如果令每条边的权值为两边的异或值,则对于每个 ,权值为 的边恰有 条。而正好需要找 棵树,这说明可以使得每棵树中,边的权值取完所有 ,可以令每棵树对应位置的边权值相同。
考虑求出图中的一个最大独立集作为根集,可以证明这个独立集的大小为 。这些根之间都至少差了两位,这样构造出来的树一定可以保证每条边都被选择了至多一次,这就是一个合法的解,时间复杂度 ,不知道为什么开 。
代码极短:
CPP#include <bits/stdc++.h>
using namespace std;
#define MAXN 20
int n, ct; vector<int> e[MAXN]; int dis[MAXN], wfa[MAXN]; bool vis[65536]; vector<int> vec;
void dfs(int x, int f){for (auto i: e[x]) if (i ^ f) wfa[i] = 1<<(ct++), dis[i] = dis[x]^wfa[i], dfs(i, x);}
signed main(){
// freopen("constr.in", "r", stdin); freopen("constr.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n; for (int i(1), u, v; i<=n; ++i) cin >> u >> v, e[u].push_back(v), e[v].push_back(u); dfs(0, -1); cout << (1<<(n-1)) << '\n';
for (int i(0); i<(1<<n); ++i) if (!vis[i]){vec.push_back(i); for (int j(0); j<n; ++j) vis[i^1<<j] = 1;}
for (auto i: vec){for (int j(0); j<=n; ++j) cout << (i^dis[j]) << ' '; cout << '\n';}
return 0;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...