【树形DP】 HDU 4756 Install Air Conditioning

通道

题意:给n个点,现在要使这n个点连通,并且要求代价最小。现在有2个点之间不能直接连通(除了第一个点),求最小代价

思路:先求mst,然后枚举边,对于生成树上的边替换,用树形dp O(N^2)求出每条生成树边的最小替代边。然后替换后的最大值

代码:

#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int inf = 0x3f3f3f3f;

inline void RD(int &ret) {
    char c;
    int flag = 1 ;
    do {
        c = getchar();
        if(c == ‘-‘)flag = -1 ;
    } while(c < ‘0‘ || c > ‘9‘) ;
    ret = c - ‘0‘;
    while((c=getchar()) >= ‘0‘ && c <= ‘9‘)
        ret = ret * 10 + ( c - ‘0‘ );
    ret *= flag ;
}
struct kdq{
    int s , e  ;
    double l ;
    bool operator <  (const kdq & fk)const {
        return l > fk.l ;
    }
} ;

#define N 1111
#define M 111111
int st[M] ;
int top ;
double NMIN[N][N] ;
int x[N] , y[N] , cost , n ;
double Map[N][N] ;
double dis[N]  ;
bool vis[N] ;
vector<int>G[N] ;
priority_queue<kdq>qe ;
double mst = 0 ;
bool ismst[N][N] ;
double MINE[N][N] ;
double getdis(int i , int j){
    return sqrt(1.0 * (x[i] - x[j]) * (x[i] - x[j]) + 1.0 * (y[i] - y[j]) * (y[i] - y[j])) ;
}

void Prim(){
    mst = 0 ;
    memset(ismst, 0, sizeof ismst);
    while(!qe.empty())qe.pop() ;
    for (int i = 0 ; i < n ; i ++ )dis[i] = Map[0][i] , vis[i] = 0 ,G[i].clear() ,qe.push((kdq){0 , i , dis[i]}) ;
    dis[0] = 0 , vis[0] = 1 ;
    while(!qe.empty()){
        kdq tp = qe.top() ; qe.pop() ;
        if(vis[tp.e])continue ;
        mst += Map[tp.s][tp.e] ;
        vis[tp.e] = 1 ;
        G[tp.s].push_back(tp.e) ; G[tp.e].push_back(tp.s) ;
        ismst[tp.e][tp.s] = ismst[tp.s][tp.e] = 1 ;
        MINE[tp.s][tp.e] = MINE[tp.e][tp.s] = inf ;//删除树边
        for (int i = 0 ; i < n ; i ++ )if(!vis[i] && dis[i] > Map[tp.e][i])dis[i] = Map[tp.e][i] , qe.push((kdq){tp.e , i , dis[i]}) ;
    }
}

void dfs(int root , int fa , int now){
    int sz = G[now].size() ;
    for (int i = 0 ; i < sz ; i ++ ){
        int e = G[now][i] ;
        if(e != fa)dfs(root , now , e) , MINE[root][now] = min(MINE[root][now] , MINE[root][e]) ;
    }
}

void dfs(int fa, int now){
    int fk = top ;
    st[ ++ top] = now ;int sz = G[now].size() ;
    for (int i = 0 ; i < sz ; i ++ ){
        int e = G[now][i] ; if(e != fa)dfs(now , e) ;
    }
    if(fa != -1){
        NMIN[now][fa] = NMIN[fa][now] = inf ;
        for (int i = fk + 1 ; i <= top ; i ++ )NMIN[now][fa] = NMIN[fa][now] = min(NMIN[fa][now] , MINE[st[i]][fa]) ;
    }
}
void solve(){scanf("%d%d", &n, &cost);
    for (int i = 0 ; i < n ; i ++ )RD(x[i]) , RD(y[i]) ;
    for (int i = 0 ; i < n ; i ++ )
        for (int j = 0 ; j < n ; j ++ )
            MINE[i][j] = Map[i][j] = (i == j) ? 0 : getdis(i , j) ;
    Prim() ;
    for (int i = 0 ; i < n ; i ++ )dfs(i , -1 , i ) ;
    top = 0 ;
    dfs(-1 , 0) ;
    double ans = 0 ;
    for (int i = 0 ; i < n ; i ++ ){
        for (int j = 0 ; j < n ; j ++ ){
            if(i == 0 || j == 0)continue ;
            if(!ismst[i][j])continue ;
            ans = max(ans , NMIN[i][j] - Map[i][j]) ;
        }
    }
    printf("%.2f\n",(ans + mst) * cost) ;
}
int main() {
    int _ ; scanf("%d", &_); while(_ --)solve() ;
    return 0 ;
}

时间: 2024-10-07 04:40:37

【树形DP】 HDU 4756 Install Air Conditioning的相关文章

hdu 4126 Genghis Khan the Conqueror hdu 4756 Install Air Conditioning 最小生成树

这两题思路一样.先说下题意. 第一道就是一张图,q个操作,每次将一个边x,y增大到z,求出此时的最小生成树的值w,输出这q个w的平均值. 第二道是一张完全图,但是有一条未知边不能选,求最小生成树最大可能是多少. 对于第一道题,先求出最小生成树,对于每个操作x,y,z,假设x,y不是树边,那么w不变,如果是树边,那么假设这条边连接了u,v两个点集,那么只要添上一条两个点集间所有边的最小的那条即可.但是复杂度为n3,所以为了降低复杂度,要预处理出这条最小边,用dp[ i ][ j ]表示i,j两集合

HDU 4756 Install Air Conditioning

Install Air Conditioning Time Limit: 2000ms Memory Limit: 65535KB This problem will be judged on HDU. Original ID: 475664-bit integer IO format: %I64d      Java class name: Main   NJUST carries on the tradition of HaJunGong. NJUST, who keeps up the ”

HDU 4756 Install Air Conditioning(次小生成树)

题目大意:给你n个点然后让你求出去掉一条边之后所形成的最小生成树. 比较基础的次小生成树吧...先prime一遍求出最小生成树,在dfs求出次小生成树. Install Air Conditioning Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 1038    Accepted Submission(s): 240 Problem

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&qu

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

Install Air Conditioning HDU - 4756 题意是要让n-1间宿舍和发电站相连 也就是连通嘛 最小生成树板子一套 但是还有个限制条件 就是其中有两个宿舍是不能连着的 要求所有情况中最大的那个 这是稠密图 用kruskal的时间会大大增加 所以先跑一遍prim 跑完之后对最小生成树里面的边去搜索(树形dp)我觉得dp就是搜索(虽然我菜到切不了dp题.) so dfs的过程我也叫做树形dp咯 dp[i][j]表示i和j不相连后 这两个部分距离最小的边 代码如下 #incl

fwt优化+树形DP HDU 5909

1 //fwt优化+树形DP HDU 5909 2 //见官方题解 3 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ 4 5 #include <bits/stdc++.h> 6 // #include <iostream> 7 // #include <cstdio> 8 // #include <cstdlib> 9 // #include <algorithm> 10 // #inc

树形dp/hdu 1011 Starship Troopers

题意 有n个房子,1号为起点房子.每个房子里会消耗一定的士兵来获取一定的价值.现在有m个士兵,求问可以获得的最大价值 注意:走过的房子不能再走 注意2:若要消灭这个房子的bugs,必须全部消灭 分析 典型的树形dp,01背包,因为每个房子里要么全杀死bugs,要么一个不动,只有取或不取两种状态 设f[i][j]表示以i为根节点,消耗j个士兵所能获得的最大价值 则f[i][j]=max(f[son[i]][k] + f[i][j-k]); 答案为f[1][m] Accepted Code 1 /*

树形DP [HDU 2196] Computer

Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3526    Accepted Submission(s): 1788 Problem Description A school bought the first computer some time ago(so this computer's id is 1). D

树形DP [HDU 1561] The more, The Better

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5506    Accepted Submission(s): 3274 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝