博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最小k度最小生成树模板
阅读量:5019 次
发布时间:2019-06-12

本文共 3040 字,大约阅读时间需要 10 分钟。

代码是抄的

题解是瞄的

可我想学习的心是真的嘤嘤嘤

然而

还是上传一份ioi大神的论文吧

链接:

密码:blr4

代码如下

#include #include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fuck(x) cout<<"["<
<<"]";#define FIN freopen("input.txt","r",stdin);#define FOUT freopen("output.txt","w+",stdout);//#pragma comment(linker, "/STACK:102400000,102400000")const int INF = 0x3f3f3f3f;const int maxn = 25; using namespace std; struct Edge{ int u, v, d; Edge() {} Edge(int a, int b, int c) : u(a), v(b), d(c) {} bool operator < (const Edge &e) const { return d < e.d; }}; int n, m, k;int cnt;int ans;int f[maxn]; // 并查集map
nodes;vector
edges;Edge dp[maxn];int g[maxn][maxn];bool tree[maxn][maxn]; // tree[i][j]=true表示
这条边在最小生成树中int minEdge[maxn]; int find(int p) { if (p == f[p]) return f[p]; return f[p] = find(f[p]);} void unite(int p, int q) { f[find(p)] = find(q);} void kruskal() { sort(edges.begin(), edges.end()); for (int i = 0; i < edges.size(); i++) { int p = edges[i].u; int q = edges[i].v; if (p == 1 || q == 1) continue; // 忽略根节点 if (find(p) != find(q)) { unite(p, q); tree[p][q] = tree[q][p] = 1; ans += edges[i].d; } }} void dfs(int cur, int pre) { for (int i = 2; i <= cnt; i++) { if (i == pre || !tree[cur][i]) continue; if (dp[i].d == -1) { if (dp[cur].d > g[cur][i]) dp[i] = dp[cur]; else { dp[i].u = cur; dp[i].v = i; dp[i].d = g[cur][i]; } } dfs(i, cur); }} void solve() { int keyPoint[maxn]; for (int i = 2; i <= cnt; i++) { if (g[1][i] != INF) { // 点i在哪颗最小生成树中 int color = find(i); // 每颗最小生成树中距离根节点最近的点与根节点的距离 if (minEdge[color] > g[1][i]) { minEdge[color] = g[1][i]; keyPoint[color] = i; } } } for (int i = 1; i <= cnt; i++) { if (minEdge[i] != INF) { m++; tree[1][keyPoint[i]] = tree[keyPoint[i]][1] = 1; ans += g[1][keyPoint[i]]; } } // 由i-1度生成树得i度生成树 for (int i = m + 1; i <= k; i++) { memset(dp, -1, sizeof(dp)); dp[1].d = -INF; for (int j = 2; j <= cnt; j++) if (tree[1][j]) dp[j].d = -INF; dfs(1, -1); // dp预处理 int idx, minnum = INF; for (int j = 2; j <= cnt; j++) { if (minnum > g[1][j] - dp[j].d) { minnum = g[1][j] - dp[j].d; idx = j; } } if (minnum >= 0) break; tree[1][idx] = tree[idx][1] = 1; tree[dp[idx].u][dp[idx].v] = tree[dp[idx].v][dp[idx].u] = 0; ans += minnum; }} void init() { memset(g, 0x3f, sizeof(g)); memset(tree, 0, sizeof(tree)); memset(minEdge, 0x3f, sizeof(minEdge)); m = 0; cnt = 1; ans = 0; nodes["Park"] = 1; for (int i = 0; i < maxn; i++) f[i] = i;} int main() {#ifndef ONLINE_JUDGE FIN#endif scanf("%d", &n); string s1, s2; int d; init(); for (int i = 1; i <= n; i++) { cin >> s1 >> s2 >> d; if (!nodes[s1]) nodes[s1] = ++cnt; if (!nodes[s2]) nodes[s2] = ++cnt; int u = nodes[s1], v = nodes[s2]; edges.push_back(Edge(u, v, d)); g[u][v] = g[v][u] = min(g[u][v], d); } scanf("%d", &k); kruskal(); // 忽略根节点先计算一次最小生成树,此时得到一个森林 solve(); printf("Total miles driven: %d\n", ans); return 0;}
View Code

 

转载于:https://www.cnblogs.com/buerdepepeqi/p/9396625.html

你可能感兴趣的文章
DLL注入新姿势:反射式DLL注入研究
查看>>
DCMTK354之VC++ 2008 MFC应用程序配置完整过程
查看>>
与一对加拿大华人夫妇的故事
查看>>
php JSON数据格式化方法
查看>>
PHP情人:p十几天来学习hp第一天
查看>>
hdu 4912 Paths on the tree(树链拆分+贪婪)
查看>>
react的基本操作(1)
查看>>
You should blog even if you have no readers--Nathan Marz
查看>>
【替代语法】PHP中冒号、endif、endwhile、endfor这些都是什么
查看>>
MyEclipse 与 eclipse 项目文件说明
查看>>
C#里面如何判断一个Object是否是某种类型
查看>>
Effective C++_笔记_条款03_尽可能使用const
查看>>
对称矩阵与压缩存储算法(java实现)
查看>>
C# ListView解读
查看>>
常用的四种设计模式 PHP代码
查看>>
释放linux的buff/cache
查看>>
ubuntu 4.10~5.10 :古老的ubuntu上安装oracle10g的情况
查看>>
hdu4063(圆与圆交+线段与圆交+最短路)
查看>>
hdu 1011(树形DP)
查看>>
call 大佬 help7——kmp 补齐 循环节
查看>>