码迷,mamicode.com
首页 > 其他好文 > 详细

Install Air Conditioning HDU - 4756(最小生成树+树形dp)

时间:2019-03-12 09:25:04      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:img   tree   alt   就是   mem   problem   one   http   condition   

 

Install Air Conditioning

 HDU - 4756

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

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

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

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

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

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

代码如下

技术图片
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
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

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

Install Air Conditioning HDU - 4756(最小生成树+树形dp)

标签:img   tree   alt   就是   mem   problem   one   http   condition   

原文地址:https://www.cnblogs.com/Mrzdtz220/p/10514472.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!