20241016下午

P1040 启发式图染色问题(color)

我们可以先想一棵树的情况,如下图所示

image

但是显然这个节点数量是 \(2 ^ k\),我们可以考虑二分图,然后你推着推着就会发现一个建图方案

image

具体来说,我们可以现在左边创建一个颜色为 \(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
*/
posted @ 2024-10-17 19:58  libohan0518  阅读(0)  评论(0编辑  收藏  举报