2024初秋集训——提高组 #39
B. 启发式图染色问题
题目描述
有这样一个问题:给定一个
现在你要 hack 以下算法:从前往后贪心的每次将点染成最小需要的颜色,代码如下:
void solve() {
int n, m;
std::cin >> n >> m;
std::vector<int> col(n + 1);
std::vector<std::vector<int> > g(n + 1);
for(int i = 1, u, v; i <= m; i ++) {
std::cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
for(int i = 1; i <= n; i ++) {
std::set<int> s;
for(int j : g[i])
if(j < i)
s.insert(col[j]);
std::vector<int> v(s.begin(), s.end());
col[i] = v.size() + 1;
for(int j = 0; j < v.size(); j ++)
if(v[j] != j + 1) {
col[i] = j + 1;
break;
}
std::cout << col[i] << " \n"[i == n];
}
std::cout << "total = " << *std::max_element(col.begin(), col.end()) << "\n";
}
你要构造一个图,使得你只需要
思路
我们考虑令
在这张图上每个点都有你的的颜色和错误算法的颜色两种,我们试着先把错误算法凑到
虽然凑到了
而之前我们凑出来的
总之就是对于每种错误算法的颜色,你都要凑出
时空复杂度均为
代码
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
const int MAXN = 1025;
int k, n;
vector<pii> edge;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> k;
n = (2 + k) * 2;
for(int i = 3; i <= n; ++i) {
for(int j = 1; j < i / 2 * 2; ++j) {
if((j & 1) ^ (i & 1)) {
edge.emplace_back(i, j);
}
}
}
cout << n << " " << edge.size() << " 2\n";
for(int i = 1; i <= n; ++i) {
cout << !(i % 2) + 1 << " \n"[i == n];
}
for(auto [x, y] : edge) {
cout << x << " " << y << "\n";
}
return 0;
}
C. 自由组队
题目描述
有
- 每名学生恰好属于一个团队。
- 第
名学生属于的团队大小在 间。
一个大小为
思路
由于此题
我们记录哪些学生已经加入了团队,并从大到小枚举团队大小。我们可以贪心地每次尽可能让
时空复杂度均未知但可过。
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 61;
int t, n, l[MAXN], r[MAXN], w[MAXN];
map<ll, int> dp;
void Solve() {
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> l[i] >> r[i];
}
for(int i = 1; i <= n; ++i) {
cin >> w[i];
}
dp.clear();
dp[0] = 0;
for(int i = n; i >= 1; --i) {
map<ll, int> now;
vector<int> ve;
for(int j = 1; j <= n; ++j) {
if(l[j] <= i && r[j] >= i) {
ve.emplace_back(j);
}
}
sort(ve.begin(), ve.end(), [](int a, int b) -> bool {
return l[a] > l[b];
});
for(auto [s, val] : dp) {
int res = n - __builtin_popcountll(s), cnt = 0;
ll k = s;
if(res < i) {
continue;
}
now[k] = (!now.count(k) ? val : max(now[k], val));
for(int x : ve) {
if(!((s >> (x - 1)) & 1)) {
k |= (1ll << (x - 1));
if(++cnt == i) {
cnt = 0;
now[k] = (!now.count(k) ? (val += w[i]) : max(now[k], (val += w[i])));
}
}
}
}
swap(now, dp);
for(auto [a, b] : now){
dp[a] = (!dp.count(a) ? b : max(dp[a], b));
}
}
if(dp.count((1ll << n) - 1)) {
cout << dp[(1ll << n) - 1] << "\n";
}else {
cout << "impossible\n";
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
for(cin >> t; t--; Solve()) {
}
return 0;
}
本文作者:yaosicheng124
本文链接:https://www.cnblogs.com/yaosicheng124/p/18473632
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步