神圣罗马帝国皇帝

来源:互联网 发布:vscode c 插件 编辑:程序博客网 时间:2024/04/19 11:23

题目描述 Problem

题目描述只是借了历史的名义而已,纯属虚构娱乐,我亵渎历史我有罪。

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

Eval=iSCiiSDi

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


输入描述 Input Description

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


输出描述 Output Description

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


样例输入 Sample Input

3 3
1 2 2 1
2 3 2 1
3 1 1 1


样例输出 Sample Output

2.000000


提示 Hint

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


数据范围 Data Size

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


分析 I Think

Eval 值最大时也会存在评估指数小于 Eval 的,但不可能大于 Eval ,所以我们就二分答案,枚举 Eval ,在图中寻找最大生成树,如果边权之和大于 0 就可能,否则不可能。其中边权为

vi=CiDiEval
Eval 的式子得出。


代码 Code

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define cost(i) a[i].cost#define u(i) a[i].u#define v(i) a[i].v#define val(i) a[i].val#define wei(i) a[i].weistruct node{    int u,v,wei,val;    double cost;    bool operator < (const node &h)const{        return cost>h.cost;    }}a[55000];int n,m;int father[10500];void read(int &);double binary(double,double);void updata(double);double maxtree();int find(int);void uni(int,int);int main(){    read(n);read(m);    for(int i=1;i<=m;++i){        read(u(i));read(v(i));read(val(i));read(wei(i));    }    printf("%.6lf",binary(0,10000));    return 0;}void read(int &_in){    _in = 0;    char ch = getchar();    while(ch>'9' || ch<'0')        ch = getchar();    while(ch<='9' && ch>='0'){        _in = _in*10+ch-'0';        ch = getchar();    }}double binary(double L,double R){    double M;    while(R-L > 1E-7){        M = (R+L)/2;        updata(M);        if(maxtree() > 0)            L = M;        else            R = M;    }    return L;}void updata(double r){    for(int i=1;i<=m;++i)        cost(i) = val(i)-r*wei(i);    for(int i=1;i<=n;++i)        father[i] = i;    sort(a+1,a+m+1);}double maxtree(){    double ans = 0;    for(int i=1,k=1;i<=m&&k<=n;++i)        if(find(u(i)) != find(v(i))){            uni(u(i),v(i));            ans += cost(i);            ++k;        }    return ans;}int find(int x){    if(father[x] != x)        father[x] = find(father[x]);    return father[x];}void uni(int x,int y){    father[find(x)] = find(y);}
0 0
原创粉丝点击