zoukankan      html  css  js  c++  java
  • LA 5713 秦始皇修路 MST

    题目链接:http://vjudge.net/contest/144221#problem/A

    题意:

    秦朝有n个城市,需要修建一些道路使得任意两个城市之间都可以连通。道士徐福声称他可以用法术修路,不花钱,也不用劳动力,但只能修一条路,因此需要慎重选择用法术修哪一条路。秦始皇不仅希望其他道路的总长度B尽量短(这样可以节省劳动力),还希望法术连接的两个城市的人口之和A尽量大,因此下令寻找一个使得A/B最大的方案。你的任务是找到这个方案。

    任意两个城市之间都可以修路,长度为两个城市之间的欧几里德距离。

    分析:肯定是在最小生成树中删边,使得其他道路尽量短,又是添加哪两个点,使得人口最多。

    就要枚举这两个点了,注意,架起来的桥,不一定是一定要删这两个点的边,而是,这两个点之间的路上的最大边。这样枚举就可以了。

    那么就是要求每两个点之间的最大权了。(⊙o⊙),这个dfs太精妙了,我想了好久,记录一下思想。

    maxcost(i,j)点 i 和 j 之间的路里面的最大权,那么,

    他等于是,他的新边,和之前的祖先的最优值。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1000 + 10;
    
    struct Edge
    {
        int u,v;
        double d;
        bool operator < (const Edge& rhs) const
        {
            return d < rhs.d;
        }
    };
    
    int x[maxn];
    int y[maxn];
    int p[maxn];
    int n;
    Edge e[maxn*maxn];
    
    vector<int> G[maxn];
    vector<double> C[maxn];
    int father[maxn];
    
    int Find_Set(int x)
    {
        if(x!=father[x])
            father[x] = Find_Set(father[x]);
        return father[x];
    }
    
    double MST()
    {
        int m = 0;
        for(int i=0; i<n; i++)
        {
            for(int j=i+1; j<n; j++)
            {
                e[m++] = (Edge)
                {
                    i,j,sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))
                };
            }
        }
        sort(e,e+m);
        for(int i=0; i<n; i++)
        {
            father[i] = i;
            G[i].clear();
            C[i].clear();
        }
        int cnt = 0;
        double ans = 0;
    
        for(int i=0; i<m; i++)
        {
            int x = e[i].u;
            int y = e[i].v;
            int fx = Find_Set(x);
            int fy = Find_Set(y);
    
            double d = e[i].d;
            if(fx!=fy)
            {
                father[fx] = fy;
                G[x].push_back(y);
                C[x].push_back(d);
                G[y].push_back(x);
                C[y].push_back(d);
                ans += d;
                if(++cnt==n-1) break;
            }
        }
        return ans;
    }
    
    double maxcost[maxn][maxn];
    vector<int> nodes;
    
    // 0 -1 0
    void dfs(int u, int fa, double facost)
    {
        for(int i = 0; i < nodes.size(); i++)
        {
            int x = nodes[i];
            maxcost[u][x] = maxcost[x][u] = max(maxcost[x][fa], facost);
        }
        nodes.push_back(u);
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i];
            if(v != fa)
                dfs(v, u, C[u][i]);
        }
    }
    
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d",&n);
            for(int i=0; i<n; i++)
                scanf("%d%d%d",&x[i],&y[i],&p[i]);
            double tot = MST();
    
            memset(maxcost,0,sizeof(maxcost));
            nodes.clear();
            dfs(0, -1, 0);
    
            double ans = -1;
    
            for(int i=0; i<n; i++)
            {
                for(int j=i+1; j<n; j++)
                {
                    ans = max(ans,(p[i]+p[j])/(tot-maxcost[i][j]));
                }
            }
            printf("%.2lf
    ",ans);
        }
    
        return 0;
    }
  • 相关阅读:
    oracle连接本地数据库
    ERWin 7.2下载安装及注册机
    关于oracle中to_char和to_date的用法
    2016年11月26号随笔(关于oracle数据库)
    SQL Server Browser服务的作用
    正则表达式
    server重启导致执行包的job运行失败
    Windows Log和SQL SERVER errorlog
    windows services创建和部署
    c# 读取App.config
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6135786.html
Copyright © 2011-2022 走看看