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 longint 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
*/