【树型dp】hdu4126
来源:互联网 发布:阿里云 收入 编辑:程序博客网 时间:2024/06/06 18:43
树型dp学习ing
一套个人感觉图论上很好的题。
题意:
有n个城镇,m条边。
现在询问q次,问v到u这条边,价值增加到w后,创造n个点的最小生成树所用的花费最少是多少。
答案累加/q如果不增加花费的话,那明显就是一个最小生成树。
但是如果增加花费的话,有两种情况。
1:增加花费的那条边跟我一开始构成的最小生成树无关。
2:增加花费的那条边在我的最小生成树上。第一种情况简单判断就好了。
第二种情况则需要进行分析。由kruskal算法我们可知。最小生成树上的所有边。都是来自不使树成环的最小边。所以我们去除一条边后,最小生成树会变成两颗最小生成树,然后我们只需要再找一条连接这两颗最小生成树最短的边即可。
我们先dp出某一个点在删除与他相邻的那个点的边后,到其他任意点的最小距离。
然后我们再dp一下。找出以v和u为根的树相连接的最小距离。当我们增加了某一条边到w时,只需要比较best[u][v]和w谁比较小即可
这道题也可以换成次小生成树。。。删边的时候假装把某条边增加到无穷大就好了
代码:
/*@resources: hdu 4126@date: 2017-08-14@author: QuanQqqqq@algorithm: tree_dp prim*/#include <bits/stdc++.h>#define ll long long#define MAXN 3005#define INF 0x3f3f3f3fusing namespace std;ll mapp[MAXN][MAXN];vector<int> vec[MAXN];int pre[MAXN]; //记录前一个点 ll dis[MAXN];bool vis[MAXN];ll dp[MAXN][MAXN];ll best[MAXN][MAXN];void init() { for (int i = 0; i < MAXN; i++) { for (int j = 0; j < MAXN; j++) { mapp[i][j] = INF; dp[i][j] = INF; } vec[i].clear(); dis[i] = INF; }}void addEdge(int v, int u) { vec[v].push_back(u); vec[u].push_back(v);}ll prim(int n) { for (int i = 1; i < n; i++) { dis[i] = mapp[0][i]; vis[i] = false; pre[i] = 0; } int k; ll mst = 0; dis[0] = INF; vis[0] = true; pre[0] = -1; for (int i = 0; i < n - 1; i++) { k = 0; for (int j = 1; j < n; j++) { if (!vis[j] && dis[j] < dis[k]) { k = j; } } vis[k] = true; mst += dis[k]; if (pre[k] != -1) { addEdge(pre[k], k); } for (int j = 1; j < n; j++) { if (!vis[j] && dis[j] > mapp[j][k]) { dis[j] = mapp[j][k]; pre[j] = k; } } } return mst;}ll dptree(int u, int fa, int root) { int len = vec[u].size(); for (int i = 0; i < len; i++) { int v = vec[u][i]; if (v == fa) { continue; } dp[root][u] = min(dp[root][u], dptree(v, u, root)); } if (root != fa) { dp[root][u] = min(dp[root][u], mapp[root][u]); } return dp[root][u];}ll dfs(int u, int fa, int root) { ll ans = dp[u][root]; int len = vec[u].size(); for (int i = 0; i < len; i++) { int v = vec[u][i]; if (v == fa) { continue; } ans = min(ans, dfs(v, u, root)); } return ans;}int main() { int n, m, u, v, q; ll w, ans, mst; while (~scanf("%d %d", &n, &m) && (n + m)) { init(); for (int i = 0; i < m; i++) { scanf("%d %d %lld", &u, &v, &w); mapp[u][v] = mapp[v][u] = min(mapp[v][u], w); } mst = prim(n); for (int i = 0; i < n; i++) { dptree(i, -1, i); } for (int i = 0; i < n; i++) { int len = vec[i].size(); for (int j = 0; j < len; j++) { v = vec[i][j]; best[i][v] = best[v][i] = dfs(v, i, i); } } scanf("%d", &q); ans = 0; for (int i = 0; i < q; i++) { scanf("%d %d %lld", &v, &u, &w); if (pre[v] != u && pre[u] != v) { ans += mst; } else { ans += mst - mapp[u][v] + min(best[u][v], w); } } printf("%.4lf\n", ans * 1.0 / q); }}/*3 30 1 30 2 21 2 530 2 31 2 60 1 6*/
阅读全文
0 0
- 【树型dp】hdu4126
- hdu4126(MST + 树形dp
- hdu4126 prim+树形dp
- hdu4126树形dp + 错误分析
- HDU4126 最小生成树+树形dp
- hdu4126 Genghis Khan the Conqueror 树形dp+最小生成树
- hdu4126 Genghis Khan the Conqueror Prim + 树形dp
- hdu4126 MST修改边后的期望值 树形dp 好题
- hdu4126 Genghis Khan the Conqueror--最小生成树 & 树形DP(待解决)
- hdu4126.Genghis Khan the Conqueror
- hdu4126.Genghis Khan the Conqueror
- hdu4126(最小生成树最佳替换边)
- 树型dp
- 树型DP
- 树型DP
- poj2378_树型DP
- hdoj1520(树型dp)
- POJ1463 - 树型DP
- 使用Eclipse + OpenCV + C++ 环境搭建(一)
- 漫谈分布式系统:三种通信范型
- hpu vj【1391】矩阵A+B
- 编程思想之多线程与多进程(2)——线程优先级与线程安全
- MTKlog分析总结
- 【树型dp】hdu4126
- Javascript学习之Map和Filter函数实现方法详解
- memset详解 设置无穷大INF
- linux部署java项目的war包
- Linux:查看目录下文件大小
- element ui里dialog关闭后清除验证条件
- criticalSection(消息之间的独立性,保证状态的一致性)
- 【jquery】凡客轮播图(仿)
- 三星C系列手机疑似要升级到安卓7.0,还另加手机数据恢复功能