http://acm.ecnu.edu.cn/problem/3247/
很简单麻,二分k,每次得到的二分结果k,乘到外国人建的轨道的价值上,之后跑一边最小生成树即可。之后判断最小花费与计划花费的大小即可。
#include <bits/stdc++.h>
#define mme(i,j) memset(i,j,sizeof(i))
using namespace std;
struct node
{
int u,v,f;
double t;
bool operator <(node x)
{
return t<x.t;
}
}rout[1000005],tp[1000005];
long long n,m,money;
int pre[1000005];
int find_x(int x)
{
if(x==pre[x])
return x;
else
return pre[x]=find_x(pre[x]);
}
bool check(double mid)
{
for(long long i=1;i<=m;i++)
{
tp[i]=rout[i];
if(tp[i].f==1)
tp[i].t*=mid;
}
for(long long int i=1;i<=n;i++)
pre[i]=i;
sort(tp+1,tp+1+m);
double ans=0;
int u,v;
for(long long i=1;i<=m;i++)
{
u=find_x(tp[i].u);
v=find_x(tp[i].v);
if(u!=v)
{
ans+=tp[i].t;
pre[u]=v;
}
}
if(ans<=money)
return true;
return false;
}
int main()
{
while(~scanf("%lld%lld%lld",&n,&m,&money))
{
for(long long i=1;i<=m;i++)
{
scanf("%d%d%lf%d",&rout[i].u,&rout[i].v,&rout[i].t,&rout[i].f);
tp[i]=rout[i];
}
double mid,l=0,r=1000000,ans=-1;
while( (r-l) >=1e-8)
{
mid = (l+r)/2;
if(check(mid))
{
l=mid;
ans = mid;
}
else
r=mid;
}
if(ans==-1.0)
ans=1.0;
printf("%.6f\n",ans);
}
return 0;
}