神圣罗马帝国皇帝

来源:互联网 发布:java自定义泛型类 编辑:程序博客网 时间:2024/03/29 07:38

神圣罗马帝国皇帝


题目描述

中世纪的德意志,战火纷飞。
近来 ZJJSHNSD 等地区为了扩大自己的版图面积,在内部分别举行了 ZJOIJSOIHNOI 以及 SDOI (或者叫 SDTSC ) 选拔了许多优秀的战士准备发动一场波及到全国各处的战争——NOI
HN 举行 HNOI 过程中,金天成,绰号光下巴(或者没胡子)红鼻子,二试怒翻盘的成绩强势成为 HN 大军的一员并被封为公爵,率领整个 HN 大军。
HN 这个地方早已不能让金天成满足了!
他在 NOI 之前发动了一场名为 PKUSC 的战役。
金天成凭借着强大的军事才能,卓越的领导能力,强势统一了德意志的大部分地区。
为他成为神圣罗马帝国的皇帝打下了坚实的基础!
现在,金天成需要加强自己统治区域内的运输,他现在有 N 块地盘,每块地盘之间都有些道路,总共有 M 条道路,第 i 条道路有两个属性:运输量 Ci 、危险指数 Di
金天成希望有一种方案,使得维护最少的道路让 N 块地盘两两之间存在通路。
并且选取出来的道路集合 S 的评估指数

Eval=iSCiiSDi

最大!
由于他日理万机,所以这件事情他就让你来做了……


输入格式

第一行两个数字 NM
接下来 M 行,每行三个数字 A,B,C,D (1A,BN)。
表示 AB 两块地盘之间有一条运输量为 C,危险指数为 D 的可用通路。


输出格式

输出一行,表示所有道路选取方案中最大的评估指数。保留 6 位小数。


样例输入

3 3
1 2 2 3 2 3 1 1 1


样例输出

2.000000


样例解释

总共三种选法{边 1,边 2},{边 2,边 3},{边 3,边 1},然后评估值分别为 21.51.5
最大评估值为 2


数据范围

10% 的数据:1N51M10
30% 的数据:1N1001M1000
100% 的数据:1N1041M51041C1041D104


Solution

同 冒险岛。
首先二分答案 k,则

Eval=iSCiiSDik

iS(CikDi)0

所以求最小生成树就可以啦!


Code

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;int n,m,fa[10010],cnt;const double maxn=1e+8*5; struct Edge{int l,r,c,d;}edge[50010];struct Rdge{int l,r;double c;}rdge[50010];bool cmp(const Rdge &x,const Rdge &y){return x.c>y.c;} int find(int x){    int tmp=x,pre;    while(tmp!=fa[tmp])tmp=fa[tmp];    while(x!=tmp){        pre=fa[x];fa[x]=tmp;x=pre;    }    return tmp;}bool judge(double x){    double sub=0;    for(int i=1;i<=m;i++){        rdge[i].l=edge[i].l; rdge[i].r=edge[i].r;        rdge[i].c=edge[i].c-edge[i].d*x;    }    for(int i=1;i<=n;i++)fa[i]=i;    sort(rdge+1,rdge+m+1,cmp); cnt=0;    for(int i=1;i<=m&&cnt<n-1;i++){        int fl=find(rdge[i].l),fr=find(rdge[i].r);        if(fl!=fr){cnt++;fa[fl]=fr;sub+=rdge[i].c;}    }    return sub>=0;}double binary(double l,double r){    while(r-l>=1e-8){        double mid=(l+r)/2;        if(judge(mid))l=mid;        else r=mid;    }    return l;}int main(){    freopen("emperor.in","r",stdin);    freopen("emperor.out","w",stdout);    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++){        scanf("%d%d%d%d",&edge[i].l,&edge[i].r,&edge[i].c,&edge[i].d);    }    printf("%.6lf\n",binary(0,maxn));    return 0;}
0 0
原创粉丝点击