日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

2019牛客暑期多校训练营(第五场)F - maximum clique 1 (最大团:补图最大独立集)

發布時間:2024/4/18 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2019牛客暑期多校训练营(第五场)F - maximum clique 1 (最大团:补图最大独立集) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

題意

求一個最大的集合,集合內的數字兩兩之間滿足不同bit數大于1
最大團:在一個無向圖中找出一個點數最多的完全圖

思路

  • 求補圖的最大獨立集:二分圖匹配、最小割
  • 可以將原圖轉為二分圖,指定建圖方向去掉重復邊,方便輸出。
  • 網絡流:最小割
  • 二分圖匹配:對沒有匹配的點dfs,輸出增廣路左點 + 不在增廣路上的右點
    默認輸出右點,如果存在矛盾點,輸出增廣路左點同時刪除增廣路右點
#include <bits/stdc++.h> #define endl '\n' const int maxn = 5e3 + 5; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; using namespace std; int girl[maxn], l[maxn], r[maxn], match[maxn]; vector<int> g[maxn]; int one(int x) {int cnt = 0;while (x) {if (x & 1) cnt++;x >>= 1;}return cnt; } int dfs(int x) {l[x] = 1;for (int i = 0; i < (int)g[x].size(); ++i) {int y = g[x][i];if (r[y]) continue;r[y] = 1;if (girl[y] == 0 || dfs(girl[y])) {girl[y] = x;return 1;}}return 0; } int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n;cin >> n;vector<int> a(n+1);for (int i = 1; i <= n; ++i) {cin >> a[i];}for (int i = 1; i <= n; ++i) {for (int j = i+1; j <= n; ++j) {if (__builtin_popcount(a[i] ^ a[j]) == 1) {if (__builtin_parity(a[i])) g[i].push_back(j);else g[j].push_back(i);}}}int cnt = 0;for (int i = 1; i <= n; ++i) {memset(r, 0, sizeof(r));cnt += (match[i] = dfs(i));}cout << n - cnt << endl;memset(l, 0, sizeof(l));memset(r, 0, sizeof(r));for (int i = 1; i <= n; ++i) {if (match[i]) continue;dfs(i);}vector<int> ans;for (int i = 1; i <= n; ++i) {if (__builtin_parity(a[i]) && l[i]) ans.push_back(a[i]);if (!__builtin_parity(a[i]) && !r[i]) ans.push_back(a[i]); }for (auto it : ans) {cout << it << " ";}cout << endl;return 0; } #include <bits/stdc++.h> #define endl '\n' const int maxn = 5e3 + 5; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; using namespace std; int one(int x) {int cnt = 0;while (x) {if (x & 1) cnt++;x >>= 1;}return cnt; } struct ac{int v, c, nex; }edge[maxn << 8]; int s, e; int head[maxn], dis[maxn], curedge[maxn], cnt; void init() {cnt = 0;memset(head, -1, sizeof(head)); } void addedge(int u, int v, int c) {// 正向建邊edge[cnt] = {v, c, head[u]};head[u] = cnt++;// 反向建邊, 流量為0edge[cnt] = {u, 0, head[v]};head[v] = cnt++; } bool bfs() {queue<int> que;que.push(s);memset(dis, 0, sizeof(dis)); // 對圖進行分層dis[s] = 1;while (!que.empty()) {int u = que.front();que.pop();for (int i = head[u]; i != -1; i = edge[i].nex) {int v = edge[i].v;int c = edge[i].c;// 如果節點v已經分過層或者u->v流量為0, continueif (dis[v] || c == 0) continue;dis[v] = dis[u] + 1; // 對v進行標記并加入隊列que.push(v);}}return dis[e] > 0; // 判斷是否存在增廣路,s是否能到達e }int dfs(int u, int flow) { // 增廣路走到u點的最小流量為flowif (u == e || flow == 0) return flow;// 遍歷u的所有出邊for (int &i = curedge[u]; i != -1; i = edge[i].nex) { // 當前弧優化int v = edge[i].v;int c = edge[i].c;// 判斷能否u->v增廣if (dis[v] != dis[u] + 1 || c == 0) continue;int d = dfs(v, min(flow, c));if (d > 0) { // 找到一條增廣路,修改增廣路上的正反向邊edge[i].c -= d;edge[i^1].c += d;return d;} }dis[u] = -1; // // 炸點優化return 0; } int Dinic() {int sum = 0, d;while (bfs()) { // 判讀是否存在增廣路for (int i = 0; i <= e; ++i) curedge[i] = head[i]; // copy head數組,在dfs中可以直接得到下一條沒有被增廣過的邊while ((d = dfs(s, inf)) > 0) sum += d; // 多次dfs找增廣路}return sum; }int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n;cin >> n;vector<int> a(n+1);for (int i = 1; i <= n; ++i) {cin >> a[i];}s = 0, e = n + 1;init();for (int i = 1; i <= n; ++i) {if (__builtin_parity(a[i])) addedge(s, i, 1);else addedge(i, e, 1);}for (int i = 1; i <= n; ++i) {for (int j = i+1; j <= n; ++j) {if (__builtin_popcount(a[i] ^ a[j]) == 1) {if (__builtin_parity(a[i])) addedge(i, j, 1);else addedge(j, i, 1);}}}cout << n - Dinic() << endl;for (int i = 1; i <= n; ++i) {if (__builtin_parity(a[i]) && dis[i]) cout << a[i] << " ";if (__builtin_parity(a[i]) == 0 && dis[i] == 0) cout << a[i] << " ";}cout << endl;return 0; }

總結

以上是生活随笔為你收集整理的2019牛客暑期多校训练营(第五场)F - maximum clique 1 (最大团:补图最大独立集)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。