HDU 4756 Install Air Conditioning (MST+树形DP)

Posted dwtfukgv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4756 Install Air Conditioning (MST+树形DP)相关的知识,希望对你有一定的参考价值。

题意:n-1个宿舍,1个供电站,n个位置每两个位置都有边相连,其中有一条边不能连,求n个位置连通的最小花费的最大值。

析:因为要连通,还要权值最小,所以就是MST了,然后就是改变一条边,然后去找出改变哪条能使得总花费最大,dp[i][j] 表示那条边左边的 i 和右边的 j,

最短距离,然后枚举MST里面的每条边,就能知道哪是最大了,注意 供电站和宿舍之间的边不能考虑的。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
//#include <tr1/unordered_map>
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std;
//using namespace std :: tr1;

typedef long long LL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 0x3f3f3f3f3f3f;
const LL LNF = 0x3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e3 + 5;
const LL mod = 10000000000007;
const int N = 1e6 + 5;
const int dr[] = {-1, 0, 1, 0, 1, 1, -1, -1};
const int dc[] = {0, 1, 0, -1, 1, -1, 1, -1};
const char *Hex[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
inline LL gcd(LL a, LL b){  return b == 0 ? a : gcd(b, a%b); }
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int Min(int a, int b){ return a < b ? a : b; }
inline int Max(int a, int b){ return a > b ? a : b; }
inline LL Min(LL a, LL b){ return a < b ? a : b; }
inline LL Max(LL a, LL b){ return a > b ? a : b; }
inline bool is_in(int r, int c){
    return r >= 0 && r < n && c >= 0 && c < m;
}
struct Point{
    double x, y;
};
struct Edge{
    int to, next;
};
Edge edge[maxn<<1];
Point a[maxn];
double dist[maxn][maxn], lowc[maxn], dp[maxn][maxn];
bool vis[maxn], is_tree[maxn][maxn];
int pre[maxn], head[maxn];
int cnt;
double sum, ans;

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));
}

void add(int u, int v){
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}

void Prim(){
    sum = 0.0;
    memset(vis, false, sizeof vis);
    memset(pre, 0, sizeof pre);
    for(int i = 1; i < n; ++i)  lowc[i] = dist[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;
        add(p, pre[p]);
        add(pre[p], p);
        for(int j = 0; j < n; ++j)
            if(!vis[j] && lowc[j] > dist[p][j])
                lowc[j] = dist[p][j], pre[j] = p;
    }
}

double dfs(int u, int fa, int root){
    double ans = fa == root ? inf : dist[root][u];
    for(int i = head[u]; ~i; i = edge[i].next){
        int v = edge[i].to;
        if(v == fa)  continue;
        double tmp = dfs(v, u, root);
        ans = min(ans, tmp);
        dp[u][v] = dp[v][u] = min(dp[u][v], tmp);
    }
    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-dist[u][v]+dp[u][v]);
        dfs1(v, u);
    }
}

int main(){
    int T;  cin >> 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)
                dist[i][j] = dist[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 *= m * 1.0;
        printf("%.2f\n", ans);
    }
    return 0;
}

 

以上是关于HDU 4756 Install Air Conditioning (MST+树形DP)的主要内容,如果未能解决你的问题,请参考以下文章

hdu4126_hdu4756_求最小生成树的最佳替换边_Kruskal and Prim

Air Raid[HDU1151]

hdu 1151 Air Raid - 二分匹配

HDU 1151 - Air Raid

HDU1151:Air Raid(最小边覆盖)

HDU1151 Air Raid(有向图最小路径覆盖)