hdu4081(最小生成树变形)

来源:互联网 发布:淘宝win10激活码木马 编辑:程序博客网 时间:2024/06/06 00:16

本题的题意是某一条路可以不用花钱,这条路所连接的两个城市权值之和为A,然后求出最小生成树所需要的代价B,求出最大的A/B

思路很清楚,因为有了这条路之后这两个点已经连通了,其他的线段肯定是最小生成树的线段(因为所需要花费的代价少于最小生成树的代价)。我们可以先将最小生成树的线段列举出来,然后将某一条边去掉,这样B的值确定,然后确定A的值,即找两个集合各自最大的节点值。


#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#define N 1005using namespace std;int G[N];double ans,answer,top;struct node{    int t,x,y;    int w;}Node[N];struct flow{    int x;int y;    double len;}Flow[N*500],flow1[N];int findx(int x){    return G[x]==x?x:G[x]=findx(G[x]);}double f(int i,int j){    double p=(Node[i].x-Node[j].x)*(Node[i].x-Node[j].x);    double q=(Node[i].y-Node[j].y)*(Node[i].y-Node[j].y);    return sqrt(p+q);}bool cmp(flow a,flow b){    return a.len<b.len;}bool compare(node a,node b){    return a.w>b.w;}int main(){    int T,n,i,j,r;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        for(i=0;i<n;i++)        {            scanf("%d %d %d",&Node[i].x,&Node[i].y,&Node[i].w);            Node[i].t=i;            G[i]=i;        }        int t=0;        for(i=0;i<n;i++)            for(j=i+1;j<n;j++)        {            Flow[t].x=i;            Flow[t].y=j;            Flow[t].len=f(i,j);            t++;        }        sort(Flow,Flow+t,cmp);        ans=0,r=0,top=0;        for(i=0;i<t;i++)        {            int p=findx(Flow[i].x);            int q=findx(Flow[i].y);            if(p!=q)            {                flow1[r].x=Flow[i].x;                flow1[r].y=Flow[i].y;                flow1[r].len=Flow[i].len;                r++;                ans+=Flow[i].len;                G[p]=q;            }        }        sort(Node,Node+n,compare);        for(i=0;i<r;i++)        {            ans-=flow1[i].len;            for(j=0;j<n;j++) G[j]=j;            for(j=0;j<r;j++)            {                if(j==i) continue;                int p=findx(flow1[j].x);                int q=findx(flow1[j].y);                if(p!=q)                {                    G[p]=q;                }            }            for(j=1;j<n;j++)            {                if(findx(Node[j].t)!=findx(Node[0].t))                {                    answer=(double)(Node[0].w+Node[j].w)/ans;                    if(top<answer) top=answer;                    break;                }            }            ans+=flow1[i].len;        }        printf("%.2f\n",top);    }    return 0;}


0 0