[Reserved] $ Luogu $ $ P4951 $ explanations

Read the original

Dichotomous answer good questions!

Although this age-old question (2001), but those who question the wisdom of the USACOduliuIt does make us wonder.

Said that Italy is given a undirected graph, each side has a time $ t $ and a profit spent $ c $, given other compensation $ f $, average seek time.

We may assume the average time profits $ ans $, the $ ans = \ frac {f - \ sum {c_i}} {\ sum {t_i}} $. Readily available to transform equation $ f - \ sum {c_i} - ans * \ sum {t_i} = 0 $.

Order function $ f (ans) = f - \ sum {c_i} - ans * \ sum {t_i} $, apparently $ f (ans) $ is a monotone, monotone decreasing in question within the scope of the present.

Therefore, we can answer half of practices employed to solve This question is for $ ans $ divided by two.

Of course, the essence of the answer is always the dichotomy $ check $ function. This question in order to examine the legality of the answer, from the preceding equation may wish to weight each edge is set to $ c_i + ans * t_i $, by running over $ Kruskal $ is easy to calculate $ \ sum {c_i} + ans * \ sum {t_i} $, $ f $ if the answer is less than this value is too small, otherwise the answer is too large.

At this point, the end of this question! The remaining details see below code. Have questions, comments and corrections area, see, thank you watch!

Further reading: minimum ratio spanning tree

This problem Code:

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
    int ret=0,f=1;
    char ch=getchar();
    while(ch>'9'||ch<'0')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        ret=(ret<<1)+(ret<<3)+ch-'0';
        ch=getchar();
    }
    return ret*f;
}
int n,m,f,fa[405];
long long mid,l,r=2e15;
struct Edge
{
    int x;
    int y;
    int c;
    int t;
    double w;
}edge[10005];
inline bool cmp(Edge a,Edge b)
{
    return a.w<b.w;
}
inline int find(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x]=find(fa[x]);
}
inline bool check(long long mid)
{
    for(register int i=1;i<=m;i++)
        edge[i].w=mid/(3e6+0.0)*edge[i].t+edge[i].c;
    int tmp=1;
    sort(edge+1,edge+m+1,cmp);
    for(register int i=1;i<=n;i++)
        fa[i]=i;
    double k=f+1e-12;
    for(register int i=2;i<=n;i++)
    {
        while(tmp<=m&&find(edge[tmp].x)==find(edge[tmp].y))
            tmp++;
        fa[find(edge[tmp].x)]=find(edge[tmp].y),k-=edge[tmp].w;
        if(k<0)
            return false;
    }
    return true;
}
int main()
{
    n=read();
    m=read();
    f=read();
    for(register int i=1;i<=m;i++)
    {
        edge[i].x=read();
        edge[i].y=read();
        edge[i].c=read();
        edge[i].t=read();
    }
    if(!check(0))
    {
        printf("0.0000\n");
        return 0;
    }
    while(l<r)
    {
        mid=(l+r)>>1;
        if(check(mid+1))
            l=mid+1;
        else
            r=mid;
    }
    printf("%0.4lf\n",l/(3e6+0.0));
    return 0;
}

Guess you like

Origin www.cnblogs.com/Peter0701/p/11298181.html