EOJ 3247 铁路修复计划 (最小生成树+二分)

铁路修复计划

Time limit per test: 2.0 seconds

Time limit all tests: 15.0 seconds

Memory limit: 256 megabytes

在 A 国有很多城际铁路。这些铁路都连接两个城市(城市从  1  到  n  编号),可以双向通行,使得任意两个城市之间都由铁路网联系起来。

不过在一次星球大战之后,所有的铁路都经历了不同程度的损伤以至于无法通行了。由于经费紧缺,A 国政府不愿意再出资造新的铁路。对于原有的城际铁路,根据铁路的实际情况,有以下两种处理办法:

  1. 使用国内技术进行修复:主要针对损坏情况不是很严重的铁路。国内公司会对铁路状况进行评估,然后如实开出铁路修复的费用。
  2. 使用国外技术进行修复:主要针对损坏情况严重的铁路。国外公司也会对铁路情况进行评估,然后按照铁路实际修复费用的  k  倍来收费(其中  k  是一个由国外公司决定的实数,不管怎么说,优惠是不可能的,所以  k1 )。

A国政府修复铁路的总预算是  M ,目标是要让任意两个城市之间都能通过铁路联系起来。在预算不够且能够完成目标的条件下,显然没必要修复每一条铁路。

国外公司通过不知什么途径了解到了 A 国政府的总预算  M ,他们现在要把  k  定下来,并且希望  k  尽可能得大。但  k 又不能太大,不然,如果 A 国政府发现无法完成任务的话,整个订单都会泡汤。

Input

测试数据包含不超过 30 个测试文件。每个测试文件是单个测试点。

第一行是三个整数  n,m,M   (2n105,n1mmin{105,n(n1)2},1M1015)

接下来  m  行,每行四个整数  ui,vi,ti,fi 。表示一条城际铁路,连接着  ui  和  vi  城市, ti  表示铁路实际修复费用。 fi=1  表示只能由国外公司修复, fi=0  表示由国内公司修复。 (1ui,vin,uivi,1ti106,fi{0,1}) 。输入保证两个城市之间不会存在多条铁路。

输入保证:

  • 在国外公司不乱收费  (k=1)  的情况下,使用预算能完成要求。
  • 完全不使用国外技术,只使用国内技术,是不能完成目标的。

Output

求  k  的最大值。输出答案与标准答案相差不超过  106  即判为正确。

Examples

input
3 3 9
1 2 1 1
1 3 2 0
2 3 1 1
output
7.000000
input
3 3 9
1 2 1 1
1 3 2 1
2 3 2 1
output
3.000000

Source

2017 华东师范大学网赛



卡排序的方式,,将cmp写在结构体内可以优化时间

#include<stdio.h>
#include<string.h>
#include<algorithm>
const double eps=3e-7;
using namespace std;
int pre[1000003];
struct data
{
    int x,y,f;
    double c;
    bool operator<(data a)
    {
        return c<a.c;
    }
} a[1000003],b[1000003];
int cmp(data x,data y)
{
    return x.c<y.c;
}
int find(int x)
{
    if(x!=pre[x])
    {
        return pre[x]=find(pre[x]);
    }
    return x;
}
void coin(int x,int y)
{
    int X=find(x);
    int Y=find(y);
    if(X!=Y)
    {
        pre[X]=Y;
    }
    return;
}
int n,m;
double k;
void init()
{
    for(int i=0; i<=n; i++)
    {
        pre[i]=i;
    }
    return;
}

int operat(double x)
{
    init();
    for(int i=0; i<m; i++)
    {
        b[i]=a[i];
        if(b[i].f)
        {
            b[i].c*=x;
        }
    }
    sort(b,b+m);
    double tem=0;
    int num=1;
    for(int i=0; i<m&&num!=n; i++)
    {
        int X=find(b[i].x);
        int Y=find(b[i].y);
        if(X!=Y)
        {
            pre[X]=Y;
            num++;
            tem+=b[i].c;
        }
    }
    if(tem<=k)
    {
        return 1;
    }
    else return 0;
}
int main()
{
    while(~scanf("%d%d%lf",&n,&m,&k))
    {
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%lf%d",&a[i].x,&a[i].y,&a[i].c,&a[i].f);
        }
        double mid,l=0,r=1000000,ans=-1;
        while( (r-l) >=1e-8)
        {
            mid = (l+r)/2;
            if(operat(mid))
            {
                l=mid;
                ans = mid;
            }
            else
                r=mid;
        }
        printf("%.6f\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值