神圣罗马帝国皇帝
2016-07-10 15:22
381 查看
题目描述 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=∑i∈SCi∑i∈SDi
最大! 由于他日理万机,所以这件事情他就让你来做了……
输入描述 Input Description
第一行两个数字 N,M 。接下来 M 行,每行三个数字 A,B,C,D(1≤A,B≤N) 。 表示 A,B 两块地盘之间有一条运输量为 C ,危险指数为 D 的可用通路。
输出描述 Output Description
输出一行,表示所有道路选取方案中最大的评估指数。 保留 6 位小数。样例输入 Sample Input
3 31 2 2 1
2 3 2 1
3 1 1 1
样例输出 Sample Output
2.000000提示 Hint
总共三种选法{边 1 ,边 2 },{边 2 ,边 3 },{边 3 ,边 1 } ,然后评估值分别为 2,1.5,1.5 。 最大评估值为 2 。数据范围 Data Size
10% 的数据: 1≤N≤5,1≤M≤10 。30% 的数据: 1≤N≤100,1≤M≤1000 。
100% 的数据: 1≤N≤104,1≤M≤5∗104。1≤C≤104,1≤D≤104 。
分析 I Think
当 Eval 值最大时也会存在评估指数小于 Eval 的,但不可能大于 Eval ,所以我们就二分答案,枚举 Eval ,在图中寻找最大生成树,如果边权之和大于 0 就可能,否则不可能。其中边权为 vi=Ci−Di∗Eval 由 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].wei struct 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); }
相关文章推荐
- SSD: Single Shot MultiBox Detector
- HDU 1429 (bfs+状态的位压缩)
- Android开发中下拉刷新如何实现
- Singleton VS 'static class'
- Mongodb 性能测试
- ConnectivityManager 确定和监控网络连接状态
- 深度学习与自然语言处理(6)_斯坦福cs224d 一起来学Tensorflow part1
- 商城(一)
- Android Support兼容包详解
- sql增删改查封装
- 添加xmlns:android="http://schemas.android.com/apk/res/android"的意思
- 用Procedure取得全月的日期
- 用户登录
- import openfire4.0.2 source code in eclipse
- 绕圈跑_纪中2930_树状数组统计
- 165. Compare Version Numbers
- Android中Context详解 ---- 你所不知道的Context
- gcc编译出现:致命错误,没有输入文件
- 空间换时间-替换空格
- css Spirtes 错位问题解决