hdu 4081 Qin Shi Huang's National Road System(★)

来源:互联网 发布:php虚拟主机 编辑:程序博客网 时间:2024/05/22 07:55
题目意思是给你一个完全图,每个点有一个权值。
求一棵生成树。你可以使其中一条边权值变成0.使得该边两点的权值和除以生成树的边权和最大。
思路:
   具有最优解的树一定有这么一个性质。除了权值变成0的边外,其余的边都必须是最小生成树的边。
   基于这点,我们就可以先求出最小生成树,然后枚举的删边。删了一条边之后就变成了两个独立集,
   而我们要在这两个集合中找一条边,使得它具有最优解。注意到,分母是固定的,所以只需在两边找到具有最大权值的点即可。
    最小生成树的复杂度n^2枚举删边加上找点的复杂度也是n^2.最后复杂度是n^2

#include <set>#include <map>#include <queue>#include <deque>#include <cmath>#include <vector>#include <string>#include <cstdio>#include <cstdlib>#include <cstring>#include <cassert>#include <iostream>#include <algorithm>using namespace std;#define L(i) i<<1#define R(i) i<<1|1#define INF  0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-9#define maxn 1000010#define MOD 1000000007#define zero(x) (((x)>0?(x):-(x))<eps)int n,last,nearvex[1010],k,fa[1010];double lowcost[1010],edge[1010][1010];double ans,weight;int a[1010];vector<int> son[10010];struct node{    int x,y,num;}cnt[1010];double get_dis(int x,int y){    return sqrt((cnt[x].x-cnt[y].x)*(cnt[x].x-cnt[y].x)+(cnt[x].y-cnt[y].y)*(cnt[x].y-cnt[y].y));}void prim(int u){    k = 0;    weight = 0;    nearvex[u] = -1;    a[k++] = u;    for(int i = 0; i <= n; i++)        son[i].clear();    for(int i = 2; i <= n; i++)    {        lowcost[i] = edge[u][i];        nearvex[i] = u;        fa[i] = u;    }    for(int i = 1; i <= n; i++)    {        int v = -1;        double Min = INF;        for(int j = 1; j <= n; j++)            if(nearvex[j] != -1 && lowcost[j] < Min)        {            Min = lowcost[j];            v = j;            last = j;        }        if(v != -1)        {            son[nearvex[v]].push_back(v);            nearvex[v] = -1;            a[k++] = v;            weight += Min;            for(int j = 1; j <= n; j++)                if(nearvex[j] != -1 && edge[v][j] < lowcost[j])            {                lowcost[j] = edge[v][j];                nearvex[j] = v;                fa[j] = v;            }        }    }}void dfs1(int fa,int en,int& Max){    if(!son[fa].size())    {        Max = max(Max,cnt[fa].num);        return;    }    for(int i = 0; i < son[fa].size(); i++)    {        if(son[fa][i] == en)            continue;        //printf("%d %d\n",fa,son[fa][i]);        Max = max(Max,cnt[son[fa][i]].num);        dfs1(son[fa][i],en,Max);    }}void dfs2(int fa,int &Max){    if(!son[fa].size())    {        Max = max(Max,cnt[fa].num);        return;    }    for(int i = 0; i < son[fa].size(); i++)    {        Max = max(Max,cnt[son[fa][i]].num);        //printf("%d %d\n",fa,son[fa][i]);        dfs2(son[fa][i],Max);    }}void solve(int x){    int m1 = -INF,m2 = -INF;    dfs1(1,a[x],m1);    dfs2(a[x],m2);    //printf("%d %d\n",m1,m2);    //printf("%f %f\n",weight,edge[a[x]][fa[a[x]]]);    //printf("%d %d\n\n",a[x],fa[a[x]]);    double t = (m1+m2)/(weight-edge[a[x]][fa[a[x]]]);    ans = max(ans,t);}int main(){    int t,C = 1;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i = 1; i <= n; i++)            scanf("%d%d%d",&cnt[i].x,&cnt[i].y,&cnt[i].num);        for(int i = 1; i <= n; i++)            for(int j = 1; j <= n; j++)                edge[i][j] = get_dis(i,j);        prim(1);        ans = 0;        //for(int i = 0 ; i < n; i++)           // printf("%d\n",a[i]);        for(int i = 1; i < n; i++)            solve(i);        printf("%.2f\n",ans);    }    return 0;}


0 0
原创粉丝点击