P1040 启发式图染色问题(color)
我们可以先想一棵树的情况,如下图所示
但是显然这个节点数量是 \(2 ^ k\),我们可以考虑二分图,然后你推着推着就会发现一个建图方案
具体来说,我们可以现在左边创建一个颜色为 \(1\) 的结点,然后我们想让颜色数量尽量多,我们直接在右边创建一个颜色为 \(2\) 的结点,并让 \(1\) 连向 \(2\) ,我们又可以在左边创建一个颜色为 \(3\) 的结点, 但是以当前点的颜色数量而言的话,还不足以创建一个颜色为 \(3\) 的点,所以我们可以在右边创建一个颜色为 \(1\) 的点,那么就可以维持了,然后让 \(2, 1\) 向 \(3\) 连边,我们考虑在左边创建一个颜色为 \(4\) 的点,但是还需要在右边创建一个颜色为三的点,而在右边创建一个颜色为 \(3\) 的点又需要在左边创建一个颜色为 \(2\) 的点,以此类推,但是如果我们在右边创建一个颜色为 \(4\) 的点,就只需要在左边创建一个颜色为 \(2\) 的点,所以我们可以果断在右边创建一个颜色为 \(4\) 的点,在左边创建一个颜色为 \(2\) 的点,那么按照这个规律向下推,我们便可以构造出一个颜色为 \(2 \times (k + 2)\) 的图
#include <bits/stdc++.h>
using namespace std;
using Pii = pair<int, int>;
#define int long long
int k, n;
vector<Pii> e;
signed main() {
freopen("color.in", "r", stdin);
freopen("color.out", "w", stdout);
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)) {
e.push_back({i, j});
}
}
}
cout << n << " " << e.size() << " 2\n";
for (int i = 1; i <= n; i++) {
if (i == n) {
cout << !(i % 2) + 1;
}
else cout << !(i % 2) + 1 << " ";
}
cout << "\n";
for (auto [x, y] : e) {
cout << x << " " << y << "\n";
}
return 0;
}
是的,代码就这么短
自由组队(teamup)
我们可以考虑直接暴搜每个队伍的长度,但是我们要保证长度是非严格递增的,我测试了一下, \(n = 60\) 大概只有 \(1e6\) 种,我们就可以放心大胆的暴搜,每次我们对于每个队伍选人,由于长度是严格递增的我们肯定是先选满足可以加入这个队伍中的 \(r_i\) 小的,所以暴搜加贪心即可
#include<bits/stdc++.h>
using namespace std;
using Pii = pair<long long, int>;
const int N = 100 + 5;
const long long INF = 1e18;
struct node {
int l, r;
}a[N];
int t, n;
long long w[N], ans;
vector<int> v[N];
map<Pii, long long> dp;
void dfs(long long now, int cnt, int last, long long val) {
if (dp.count({now, last}) && dp[{now, last}] > val) {
return ;
}
dp[{now, last}] = val;
if (!now) {
ans = max(ans, val);
}
for (int i = last; i <= n - cnt + 1; i++) {
long long tmp = now;
int tot = 0;
for (auto cur : v[i]) {
if (tmp & (1ll << (cur - 1))) {
tmp ^= (1ll << (cur - 1));
tot++;
}
if (tot == i) {
break;
}
}
if (tot == i) {
dfs(tmp, cnt + i, i, val + w[i]);
}
}
}
bool cmp(node _x, node _y) {
return _x.l < _y.l;
}
void Solve() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].l >> a[i].r;
}
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; i++) {
vector<Pii> tmp;
for (int j = 1; j <= n; j++) {
if (a[j].l <= i && a[j].r >= i) {
tmp.push_back({a[j].r, j});
}
}
sort(tmp.begin(), tmp.end());
for (auto cur : tmp) {
v[i].push_back(cur.second);
}
}
ans = -INF;
dfs((1ll << n) - 1, 1, 1, 0);
if (ans <= -1e17) {
cout << "impossible\n";
}
else cout << ans << "\n";
for (int i = 1; i <= n; i++) {
v[i].clear();
}
dp.clear();
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
freopen("teamup.in", "r", stdin);
freopen("teamup.out", "w", stdout);
cin >> t;
while (t--) {
Solve();
}
return 0;
}
/*
1
3
2 3
1 2
2 2
4 5 100
*/
标签:20241016,颜色,int,创建,下午,long,last,now
From: https://www.cnblogs.com/libohan/p/18472961