简单起见,直接用mask遍历所有情况也就是从0-2n。 时间复杂度是O(2n·n2) #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<unsigned long long> adj(n, 0); vector<vector<long long>> w(n, vector<long long>(n, 0)); for (int i = 0; i < m; i++) { int u, v; long long ww; cin >> u >> v >> ww; --u; --v; if (u == v) continue; adj[u] |= (1ULL << v); adj[v] |= (1ULL << u); w[u][v] = w[v][u] = max(w[u][v], ww); // 重边取最大,想累加就改这里 } long long bestW = LLONG_MIN; unsigned long long bestMask = 0; //最优2进制团 unsigned long long ALL = (n == 64 ? ~0ULL : ((1ULL << n) - 1)); for (unsigned long long mask = 1; mask <= ALL; mask++) { bool ok = true; //ok标记当前mask是不是团,如果不是团继续下一个mask(也就是mask++) for (int i = 0; i < n; i++) { if (mask & (1ULL << i)) //i在当前mask里面 { unsigned long long others = mask & ~(1ULL << i); //others是i之外的mask之内的点 if (others & ~adj[i]) //如果这些i之外的mask之内的点与i之间存在没有边的情况就说明不是团,ok=false { ok = false; break; } } } if (!ok) continue; //如果不能成团直接排除这个mask long long sum = 0; for (int i = 0; i < n; i++) if (mask & (1ULL << i)) //i点在mask内 for (int j = i + 1; j < n; j++) if (mask & (1ULL << j)) //j点也在musk内 sum += w[i][j]; //直接加上w[i][j]因为就算没有边权值也是0不影响结果 if (sum > bestW) { bestW = sum; bestMask = mask; } //记录最大团 } cout << bestW << "\n"; bool first = true; for (int i = 0; i < n; i++) if (bestMask & (1ULL << i)) { if (!first) cout << ' '; first = false; //这两行是输出格式化的,美观 cout << (i + 1); //下标转换为序号 } cout << "\n"; return 0; }
Learn Process
图论 最大流 最短路径 最小生成树
Cpp常用结构
1.unordered_set 用处 图结构常删除点边的时候可以用避免重复查找。 函数 insert(),find(),erase(type)(删除指定元素),clear() 2.memset 用法 void *memset(void *str, int c, size_t n) 参数 str – 指向要填充的内存区域的指针。 c – 要设置的值,通常是一个无符号字符。 n – 要被设置为该值的字节数。 例子 memset(str,'$',7); memset(nums,0,sizeof(nums));
对电脑操作记录
管理员身份运行cmd输入了powercfg -h off(【建议收藏】全网最详细C 盘清理指南!!!绝对值得收藏!!!_哔哩哔哩_bilibili) D:\Program Files\JiJiDown
图的染色解决
染色问题 同染色(连接点染相同颜色) 用法 得到各个连通分量(分组)。 代码 #include<bits/stdc++.h> using namespace std; const int MAXN = 100; int graph[MAXN][MAXN]; int color[MAXN]; int cnt; //连通分量数量 void dfs(int index,int n,int c) { color[index]=c; for(int i=0;i<n;i++) if(graph[index][i]&&!color[i]) dfs(i,n,c); } int main() { int n,m; cin >> n >> m; for(int i=0;i<m;i++) { int s,t; cin >> s >> t; graph[s][t]=1,graph[t][s]=1; } for(int i=0;i<n;i++) { if(!color[i]) { cnt++; dfs(i,n,cnt); } } vector<vector<int>> group(cnt+1,vector<int>()); for(int i=0;i<n;i++) group[color[i]].push_back(i); for(int i=1;i<=cnt;i++) { cout << "颜色" << i << ":"; for(int j=0;j<group[i].size();j++) cout << group[i][j] << ' '; cout << endl; } } 异染色(连接点染不同颜色) 用法 得到二分图。 代码 #include<bits/stdc++.h> using namespace std; const int MAXN = 100; //假如最大100个结点的图 int graph[MAXN][MAXN]; int color[MAXN]; //用于确定分组,颜色为1和2 int dfs(int index,int n,int c) //仅仅用来染色出发点所在的连通分量 { //直接用对边不同色考虑 color[index]=c; for(int i=0;i<n;i++) if(graph[index][i] && (color[i]==c || (color[i]==0 && !dfs(i,n,3-c))) ) return 0; return 1; } int main() { int n,m; cin >> n >> m; for(int i=0;i<m;i++) { int s,t; cin >> s >> t; graph[s][t]=1,graph[t][s]=1; } for(int i=0;i<n;i++) { if(!color[i]) if(!dfs(i,n,1)) { cout << "错误,不是二分图" << endl; return 0; } } vector<int> color1,color2; for(int i=0;i<n;i++) { if(color[i]==1) color1.push_back(i); if(color[i]==2) color2.push_back(i); } cout << "染色结果:" << endl; for(int i=0;i<color1.size();i++) cout << color1[i] << ' '; cout << endl; for(int i=0;i<color2.size();i++) cout << color2[i] << ' '; return 0; } 注 这两个染色问题都可以用邻接矩阵做。我用int-MAXN是因为简单:)。
归并排序
P1177 【模板】排序 - 洛谷 我用归并排序写的。(时间复杂度O(nlogn),空间复杂度O(n))。 #include<bits/stdc++.h> using namespace std; vector<int> A; //归并排序 void gbsort(int l,int r) { vector<int> temp; if(l==r) return; int m=((l+r)>>1); printf("划分的区间:[%d,%d],[%d,%d]\n",l,m,m+1,r); gbsort(l,m); gbsort(m+1,r); int curL=l,curR=m+1; //左右分为[l,m] [m+1,r] for(int i=0;i<r-l+1;i++) { if( curL>m ) { temp.push_back(A[curR]); curR++; } else if( curR>r ) { temp.push_back(A[curL]); curL++; } else if(A[curL]>A[curR]) { temp.push_back(A[curR]); curR++; } else if(A[curL]<=A[curR]) { temp.push_back(A[curL]); curL++; } } for(int i=l;i<=r;i++) { A[i]=temp[i-l]; } } int main() { int N; cin >> N; for(int i=0;i<N;i++) { int x; cin >> x; A.push_back(x); } // sort(A.begin(),A.end()); gbsort(0,N-1); for(int i=0;i<N;i++) { cout << A[i] << ' '; } return 0; } C++标准库sort用的是快速排序
洛谷 P1559
运动员最佳匹配问题 问题前面就不多说,简单模拟得到矩阵。 然后对矩阵用匈牙利得到最小匹配。 我累了,看代码吧 #include <bits/stdc++.h> using namespace std; const int MAXN = 25; int n; int P[MAXN][MAXN], Q[MAXN][MAXN]; int cost[MAXN][MAXN]; int u[MAXN], v[MAXN], p[MAXN], way[MAXN]; int hungarian() { for (int i = 1; i <= n; i++) { p[0] = i; int j0 = 0; vector<int> minv(n+1, INT_MAX); vector<bool> used(n+1, false); do { used[j0] = true; int i0 = p[j0], delta = INT_MAX, j1 = 0; for (int j = 1; j <= n; j++) { if (!used[j]) { int cur = -cost[i0][j] - u[i0] - v[j]; // 取负数求最大匹配 if (cur < minv[j]) { minv[j] = cur; way[j] = j0; } if (minv[j] < delta) { delta = minv[j]; j1 = j; } } } for (int j = 0; j <= n; j++) { if (used[j]) { u[p[j]] += delta; v[j] -= delta; } else { minv[j] -= delta; } } j0 = j1; } while (p[j0] != 0); do { int j1 = way[j0]; p[j0] = p[j1]; j0 = j1; } while (j0); } int result = 0; for (int j = 1; j <= n; j++) result += cost[p[j]][j]; return result; } int main() { cin >> n; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> P[i][j]; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cin >> Q[i][j]; // 构造竞赛优势矩阵 for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) cost[i+1][j+1] = P[i][j] * Q[j][i]; cout << hungarian() << endl; return 0; }
Hugo博客添加代码框复制功能
由于鼠标拖动复制代码有点费力,我打算给每个代码块添加一个复制按钮(学学大佬orz )。 经过长时间的搜索学习,我终于加上了(win)。 话不多说。 构建 首先,我们要清楚一点,hugo-papermod本身是不包含代码复制按钮功能的。 所以,我们要自己写,包括写css和js,同时要修改hugo的相关配置。 步骤 1.写css/js文件 static\css\extended\code-copy.css(注意不要写错地方了,当然放在assests/css里面也未尝不可,但是相应的要修改一些文件,本人懒得搞了=-=) .highlight-copy-btn { position: absolute; top: 7px; right: 7px; border: 0; border-radius: 4px; width: 28px; /* 固定按钮大小 */ height: 28px; background-color: #777; color: #fff; display: flex; /* flex 布局 */ align-items: center; /* 垂直居中 */ justify-content: center; /* 水平居中 */ cursor: pointer; padding: 0; /* 去掉多余 padding */ } .highlight-copy-btn:hover { background-color: #666; } /* 控制 svg 图标大小 */ .highlight-copy-btn i svg { width: 16px; height: 16px; display: block; /* 避免 inline 导致偏上 */ } static\js\code-copy.js (function() { 'use strict'; // 切换图标 function flashCopyMessage(el, iconName) { el.innerHTML = `<i data-feather="${iconName}"></i>`; feather.replace(); // 更新图标 setTimeout(function() { el.innerHTML = '<i data-feather="copy"></i>'; // 恢复复制图标 feather.replace(); }, 1000); } // 复制文本 async function copyText(text, btn) { try { await navigator.clipboard.writeText(text); flashCopyMessage(btn, 'check'); // 成功图标 } catch (e) { flashCopyMessage(btn, 'x'); // 失败图标 } } // 为每个代码块添加按钮 function addCopyButton(containerEl) { var copyBtn = document.createElement("button"); copyBtn.className = "highlight-copy-btn"; copyBtn.innerHTML = '<i data-feather="copy"></i>'; var codeEl = containerEl.querySelector("pre code"); if (!codeEl) return; copyBtn.addEventListener('click', function() { copyText(codeEl.innerText, copyBtn); }); containerEl.style.position = "relative"; containerEl.appendChild(copyBtn); feather.replace(); // 初始化图标 } // 初始化所有高亮块 function init() { var highlightBlocks = document.getElementsByClassName('highlight'); Array.prototype.forEach.call(highlightBlocks, addCopyButton); } document.addEventListener("DOMContentLoaded", init); })(); 2.修改配置文件 1. 把themes\PaperMod\layouts\partials\head.html拷贝一份到layouts\partials\head.html然后修改后者(模板覆盖规则): ...
匈牙利算法_指派问题
不详解,看例题就完了。