首页 > 其他 > 详细

【洛谷P3199】[HNOI2009]最小圈

时间:2017-10-30 22:38:52      阅读:317      评论:0      收藏:0      [点我收藏+]

题目描述

对于一张有向图,要你求图中最小圈的平均值最小是多少,即若一个圈经过k个节点,那么一个圈的平均值为圈上k条边权的和除以k,现要求其中的最小值。

输入输出格式

输入格式:

第一行2个正整数,分别为n和m

以下m行,每行3个数,表示边连接的信息,

输出格式:

一行一个数,表示最小圈的值,保留8位小数。

说明

若设边权为v,那么50000n≤3000,m≤10000,v≤50000。

分析

此题要求最小圈平均值最小是多少。如果这个圈的平均值是负数那么这就是一个负环。判断负环可以用spfa,然后用二分答案做就行了。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef double db;
const int maxn=3005;
const int maxm=10005;
const db eps=1e-10;
inline void read(int &x){
    x=0; char ch=getchar();
    while(ch<0||ch>9) ch=getchar();
    while(ch>=0&&ch<=9){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
}
int n,m,tot;
int head[maxn];
double dis[maxn];
bool vis[maxn];
struct node{
    int next,to,dist;
}e[maxm<<1];
inline void ins(int from,int to,int dist){
    e[++tot].next=head[from];
    e[tot].to=to; e[tot].dist=dist;
    head[from]=tot;
}
bool spfa(int x,db lim){
    vis[x]=true;
    for(int i=head[x];i;i=e[i].next){
        int to=e[i].to;
        if(dis[to]>dis[x]+(db)e[i].dist-lim){
            if(vis[to]) return true;
            else{
                dis[to]=dis[x]+(db)e[i].dist-lim;
                if(spfa(to,lim)) return true;
            }
        }
    } 
    return vis[x]=false;
}
inline bool pd(double lim){
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    for(int i=1;i<=n;++i)
    if(spfa(i,lim)) return true;
    return false;
}
int main(){
    read(n);read(m);
    for(int i=1;i<=m;++i){
        int u,v,w; read(u);read(v);read(w);
        ins(u,v,w);
    }
    db l=0.0,r=50000.0,mid;
    while(r-l>eps){
        mid=(l+r)/2.0;
        if(pd(mid)) r=mid;
        else l=mid;
    }
    printf("%.8lf",r);
    return 0;
}
    

 

【洛谷P3199】[HNOI2009]最小圈

原文:http://www.cnblogs.com/huihao/p/7757977.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!