博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Install Air Conditioning HDU - 4756(最小生成树+树形dp)
阅读量:5793 次
发布时间:2019-06-18

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

 

 

题意是要让n-1间宿舍和发电站相连 也就是连通嘛 最小生成树板子一套

但是还有个限制条件 就是其中有两个宿舍是不能连着的 要求所有情况中最大的那个

这是稠密图 用kruskal的时间会大大增加 所以先跑一遍prim

跑完之后对最小生成树里面的边去搜索(树形dp)我觉得dp就是搜索(虽然我菜到切不了dp题。)

so dfs的过程我也叫做树形dp咯

dp[i][j]表示i和j不相连后 这两个部分距离最小的边

代码如下

#include 
#include
#include
#include
using namespace std;const int maxn = 1e3 + 10;const double inf = 0x3f3f3f3f3f3f;double d[maxn][maxn], lowc[maxn], dp[maxn][maxn];bool vis[maxn], is_tree[maxn][maxn];int pre[maxn], head[maxn];int cnt, n, m;double sum, ans;struct Point { double x, y;} a[maxn];struct Edge { int to, next;} edge[maxn<<1];inline double distan(const Point& lhs, const Point& rhs) { return sqrt((lhs.x - rhs.x) * (lhs.x - rhs.x) + (lhs.y - rhs.y) * (lhs.y - rhs.y));}inline void addedge(int u, int v) { edge[cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt++;}void Prim() { sum = 0.0; memset(vis, 0, sizeof(vis)); memset(pre, 0, sizeof(pre)); for (int i = 1; i < n; i++) lowc[i] = d[0][i]; vis[0] = true; for (int i = 1; i < n; i++) { double minc = inf; int p = -1; for (int j = 0; j < n; j++) { if (!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } } sum += minc; vis[p] = true; addedge(p, pre[p]); addedge(pre[p], p); for (int j = 0; j < n; j++) { if (!vis[j] && lowc[j] > d[p][j]) { lowc[j] = d[p][j]; pre[j] = p; } } }}double dfs(int u, int fa, int root) { double ans = fa == root ? inf : d[root][u]; for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa) continue; double temp = dfs(v, u, root); ans = min(ans, temp); dp[u][v] = dp[v][u] = min(dp[u][v], temp); } return ans;}void dfs1(int u, int fa) { for (int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].to; if (v == fa) continue; if (fa) ans = max(ans, sum - d[u][v] + dp[u][v]); dfs1(v, u); }}int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) scanf("%lf%lf", &a[i].x, &a[i].y); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { d[i][j] = d[j][i] = distan(a[i], a[j]); } } cnt = 0; memset(head, -1, sizeof(head)); Prim(); for (int i = 0; i < n; ++i) for (int j = 0; j < n; ++j) dp[i][j] = inf; for (int i = 0; i < n; i++) dfs(i, -1, i); ans = sum; dfs1(0, 0); ans *= 1.0 * m; printf("%.2f\n", ans); } return 0;}
View Code

最小生成树的各种题型根本没掌握...新生赛后要补补这块和并查集的坑了...

转载于:https://www.cnblogs.com/Mrzdtz220/p/10514472.html

你可能感兴趣的文章
v$archive_gap dg dataguard 断档处理 scn恢复
查看>>
问责IT风险管理:CIO需关注两个重点
查看>>
Winform打包发布图解
查看>>
PDF文件怎么编辑,超简单的方法
查看>>
EasyUI基础入门之Easyloader(载入器)
查看>>
Uva 839 Not so Mobile
查看>>
30款超酷的HTTP 404页面未找到错误设计
查看>>
程序猿必备 MyEclipse2013-2014系列
查看>>
java中ArrayList 、LinkList区别
查看>>
Spring ’14 Wave Update: Installing Dynamics CRM on Tablets for Windows 8.1
查看>>
利用rand7()构造rand10()
查看>>
MySQL 备份与恢复
查看>>
吃午饭前,按书上的代码写会儿--Hunt the Wumpus第一个版本
查看>>
easyui中combobox的值改变onchang事件
查看>>
TEST
查看>>
PAT A1037
查看>>
ReactiveSwift源码解析(三) Signal代码的基本实现
查看>>
(六)Oracle学习笔记—— 约束
查看>>
[Oracle]如何在Oracle中设置Event
查看>>
top.location.href和localtion.href有什么不同
查看>>