枚举+最小生成树 hdoj4081 Qin Shi Huang's National Road System
2017-05-21 18:26
489 查看
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4081
题目大意是给你一个图,既有点权又有边权,求一个生成树,你可以任选其中一条边,使它的边权为0,最终使得边权为0的两点的点权和/剩余边的边权和 最小。
我们可以这样思考,从最小生成树中去掉一条边,剩余的两个连通分量用边权为0的边链接。这样是正确的,因为如果你要选择两个点并用0边把它们连接起来,意味着需要在此基础上做一颗最小生成树,求最小生成树的算法是贪心的,因此在此基础上的最小生成树除了0边之外,其他边的集合是原来最小生成树的子集(或者如果存在多棵最小生成树,边权和是相同的)。接下来就是选择0边连接哪两个节点的问题了,显然连接两个点权最大的节点。枚举删去n-1条边,取最大的即是答案。
题目大意是给你一个图,既有点权又有边权,求一个生成树,你可以任选其中一条边,使它的边权为0,最终使得边权为0的两点的点权和/剩余边的边权和 最小。
我们可以这样思考,从最小生成树中去掉一条边,剩余的两个连通分量用边权为0的边链接。这样是正确的,因为如果你要选择两个点并用0边把它们连接起来,意味着需要在此基础上做一颗最小生成树,求最小生成树的算法是贪心的,因此在此基础上的最小生成树除了0边之外,其他边的集合是原来最小生成树的子集(或者如果存在多棵最小生成树,边权和是相同的)。接下来就是选择0边连接哪两个节点的问题了,显然连接两个点权最大的节点。枚举删去n-1条边,取最大的即是答案。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <vector> using namespace std; const int MAX = 1005; const double INF = 1e10; double map[MAX][MAX], xx[MAX], yy[MAX]; int n, p[MAX], vis[MAX], fu, fv, pmax; struct edge { int u, v; double w; } dis[MAX], e[MAX]; vector<int> ve[MAX]; void init(void) { memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; i ++) ve[i].clear(); pmax = 0; } inline double dist(double x1, double y1, double x2, double y2) { return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); } int dfs(int x) { vis[x] = 1; if (p[x] > pmax) pmax = p[x]; for (int i = 0; i < ve[x].size(); i ++) { if (!vis[ve[x][i]] && !(fu == x && fv == ve[x][i] || fu == ve[x][i] && fv == x)) { dfs(ve[x][i]); } } } double prim(void) { double ret = 0; vis[1] = 1; for (int i = 1; i <= n; i ++) { dis[i].w = map[1][i]; dis[i].u = 1; dis[i].v = i; } for (int i = 1; i <= n - 1; i ++) { double min = INF; int minid; for (int j = 1; j <= n; j ++) { if (!vis[j] && dis[j].w < min) { min = dis[j].w; minid = j; } } vis[minid] = 1; ret += min; e[i] = dis[minid]; ve[e[i].u].push_back(e[i].v); ve[e[i].v].push_back(e[i].u); for (int j = 1; j <= n; j ++) { if (!vis[j] && dis[j].w > map[minid][j]) { dis[j].w = map[minid][j]; dis[j].u = minid; } } } return ret; } int main() { int t; scanf("%d",&t); while (t --) { init(); scanf("%d",&n); for (int i = 1; i <= n; i ++) { scanf("%lf%lf%d",&xx[i], &yy[i], &p[i]); for (int j = 1; j < i; j ++) { map[i][j] = map[j][i] = dist(xx[i], yy[i], xx[j], yy[j]); } map[i][i] = INF; } double len = prim(); double ans = -INF; int pp; for (int i = 1; i <= n - 1; i ++) { memset(vis, 0, sizeof(vis)); pmax = 0; fu = e[i].u; fv = e[i].v; dfs(fu); pp = 0; pp += pmax; memset(vis, 0, sizeof(vis)); pmax = 0; dfs(fv); pp += pmax; ans = max(ans, pp / (len - e[i].w)); } printf("%.2lf\n", ans); } return 0; }
相关文章推荐
- HDU 4081 Qin Shi Huang's National Road System(最小生成树+暴力枚举边)
- HDU 4081 Qin Shi Huang's National Road System(最小生成树/次小生成树)
- HDU 4081 Qin Shi Huang's National Road System(最小生成树,记录圈中最大边后暴力枚举)
- 【hdoj 4081】 Qin Shi Huang's National Road System 【次小生成树 应用变形】
- hdu 4081 Qin Shi Huang's National Road System 【最小生成树的变形】
- HDU 4081 Qin Shi Huang's National Road System(次小生成树-Kruskal)
- HDU 4081 Qin Shi Huang's National Road System 次小生成树
- HDOJ 4081 Qin Shi Huang's National Road System
- 【Prim 求次小生成树】HDU 4081 Qin Shi Huang's National Road System
- hdoj 4081 Qin Shi Huang's National Road System(次小生成树变形)
- HDU 4081 Qin Shi Huang's National Road System【次小生成树】【模板题】
- HDOJ 4081: Qin Shi Huang's National Road System
- HDOJ 4081 Qin Shi Huang's National Road System (次小生成树变形--prime)
- HDU 4081 Qin Shi Huang's National Road System【次小生成树】
- hdu 4081 Qin Shi Huang's National Road System 最优比率生成树
- uva 1494 - Qin Shi Huang's National Road System(最小生成树)
- Qin Shi Huang's National Road System - HDU 4081 - 次小生成树
- HDU 4081 Qin Shi Huang's National Road System
- UVALive5713[Qin Shi Huang's National Road System] 枚举+每对节点间最小瓶颈路
- LA5713 Qin Shi Huang's National Road System 生成树