bzoj 1486: [HNOI2009]最小圈

来源:互联网 发布:java连接ldap实例 编辑:程序博客网 时间:2024/05/21 17:14

题意:

求一个圈,使它边权的平均值最小,输出那个值。

题解:

分数规划。
二分下答案,将每条边的权值减去二分值,假如存在负环,说明有更小的解,否则没有。
像这样求平均值的题可以考虑二分+减权。
code:

#include<cstdio>#include<cstdlib>#include<iostream>#include<cstring>using namespace std;const double eps=1e-10;int n,m;struct node{    int y,next;    double c;}a[10010];int last[3010],len=0;int X[10010],Y[10010];double C[10010];void ins(int x,int y,double c){    a[++len].y=y;a[len].c=c;    a[len].next=last[x];last[x]=len;}bool vis[3010];double dis[3010];bool ty;void spfa(int x){    vis[x]=true;    for(int i=last[x];i;i=a[i].next)    {        if(ty) return;        int y=a[i].y;        if(dis[x]+a[i].c<dis[y])        {            if(vis[y]){ty=true;return;}            dis[y]=dis[x]+a[i].c;            spfa(y);        }    }    vis[x]=false;}bool check(double c){    memset(last,0,sizeof(last));len=0;    for(int i=1;i<=m;i++)        ins(X[i],Y[i],C[i]-c);    memset(vis,false,sizeof(vis));    memset(dis,0,sizeof(dis));    ty=false;    for(int i=1;i<=n;i++)    {        spfa(i);        if(ty) return true;    }    return false;}int main(){    scanf("%d %d",&n,&m);    for(int i=1;i<=m;i++) scanf("%d %d %lf",&X[i],&Y[i],&C[i]);    double l=-10000000,r=10000000;    while(l+eps<r)    {        double mid=(l+r)/2;        if(check(mid)) r=mid;        else l=mid;    }    printf("%.8lf",l);}
原创粉丝点击