Install Air Conditioning HDU

来源:互联网 发布:java 游戏开发txt下载 编辑:程序博客网 时间:2024/05/17 08:12

参考http://blog.csdn.net/fipped/article/details/39560869

题意:给n个点,现在要使这n个点连通,并且要求代价最小。现在有2个点之间不能直接连通(除了第一个点),求最小代价。思路:和HDU4126差不多,思路基本借鉴于http://blog.csdn.net/ophunter_lcm/article/details/12030593

别人的代码

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#include <cmath>using namespace std;const int N = 1010;const int M = 300010;const int inf = 0x3f3f3f3f;typedef long long ll;int pre[N], head[N], flag[N];int vis[N][N];double low[N];double dis[N][N], dp[N][N];struct node{    int x, y;} a[N];struct M_node{    int to, next;} e[M];int n, m, num;double sum;void build(int s, int t){    e[num].to = t;    e[num].next = head[s];    head[s] = num ++;}double Dis(int x1, int y1, int x2, int y2){    return sqrt(1.0 * (x1 - x2) * (x1 - x2) + 1.0 * (y1 - y2) * (y1 - y2));}void init(){    sum = 0;    num = 0;    memset(flag, 0, sizeof(flag));    memset(vis, 0, sizeof(vis));    memset(head, -1, sizeof(head));    memset(dp, 0, sizeof(dp));}void prim(){    int i, j;    for(i = 1; i <= n; i ++)    {        low[i] = dis[1][i];        pre[i] = 1;    }    flag[1] = 1;    for(i = 1; i < n; i ++)    {        double Min = inf;        int v;        for(j = 1; j <= n; j ++)        {            if(flag[j] == 0 && low[j] < Min)            {                Min = low[j];                v = j;            }        }        sum += Min;        vis[pre[v]][v] = vis[v][pre[v]] = 1;        build(v, pre[v]);        build(pre[v], v);        flag[v] = 1;        for(j = 1; j <= n; j ++)        {            if(flag[j] == 0 && low[j] > dis[v][j])            {                low[j] = dis[v][j];                pre[j] = v;            }        }    }}double dfs(int cur, int u, int fa)  //用cur更新cur点所在的子树和另外子树的最短距离{    double ans = inf;    for(int i = head[u]; ~i; i = e[i].next) //沿着生成树的边遍历    {        if(e[i].to == fa)            continue;        double tmp = dfs(cur, e[i].to, u);  //用cur更新的以当前边为割边的两个子树最短距离        ans = min(tmp, ans);        //以(fa,u)为割边的2个子树的最短距离        dp[u][e[i].to] = dp[e[i].to][u] = min(tmp, dp[u][e[i].to]);    }    if(cur != fa)   //生成树边不更新        ans = min(ans, dis[cur][u]);    return ans;}int main(){    int t, i, j;    scanf("%d", &t);    while(t --)    {        init();        scanf("%d%d", &n, &m);        for(i = 1; i <= n; i ++)            scanf("%d%d", &a[i].x, &a[i].y);        for(i = 1; i <= n; i ++)            for(j = 1; j <= i; j ++)            {                dp[i][j] = dp[j][i] = inf;                if(i == j)                    dis[i][j] = 0;                else                    dis[i][j] = dis[j][i] = Dis(a[i].x, a[i].y, a[j].x, a[j].y);            }        prim();        double ans = sum;        for(i = 0; i < n; i++)            dfs(i, i, -1);        for(i = 2; i <= n; i++)        {            for(j = 2; j < i; j++)                if(vis[i][j])                    ans = max(ans, sum - dis[i][j] + dp[i][j]);        }        printf("%.2lf\n", ans * m);    }    return 0;}
原创粉丝点击