BZOJ-1486: [HNOI2009]最小圈(二分判定+DF

作者: acccccc | 来源:发表于2018-10-17 12:25 被阅读0次

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1486

二分判定最小平均值,如果我们枚举一个端点mid,我们对所有边权减去mid,如果存在负权圈,那么就说明存在比枚举值更小的平均值,反之不存在,然后二分即可。

代码:

#include <cstdio>

#include <algorithm>

#include <cstring>

 

using namespace std ;

 

#define esp 0.0000000001

#define MAXN 3010

 

const double inf = double( 0x7fffffff ) * double( 0x7fffffff ) ;

 

struct edge {

    edge *next ;

    int t ;

    double d ;

    edge(  ) {

        next = NULL ;

    }

} *head[ MAXN ] ;

 

int n , m ;

 

void AddEdge( int s , int t , double d ) {

    edge *p = new( edge ) ;

    p -> t = t , p -> d = d , p -> next = head[ s ] ;

    head[ s ] = p ;

}

 

int cnt[ MAXN ] ;

double dist[ MAXN ] ;

bool f[ MAXN ] , flag , vis[ MAXN ] ;

 

void dfs( int v ) {

    f[ v ] = true ;

    for ( edge *p = head[ v ] ; p ; p = p -> next ) {

        if ( dist[ p -> t ] > dist[ v ] + p -> d ) {

            if ( ! f[ p -> t ] ) {

                dist[ p -> t ] = dist[ v ] + p -> d ;

                dfs( p -> t ) ;

            } else flag = true ;

            if ( flag ) break ;

        }

    }

    f[ v ] = false ;

}

 

bool check(  ) {

    memset( f , false , sizeof( f ) ) ;

    for ( int i = 0 ; i ++ < n ; ) dist[ i ] = 0 ;

    flag = false ;

    for ( int i = 0 ; i ++ < n ; ) {

        dfs( i ) ; if ( flag ) return false ;

    }

    return true ;

}

 

int main(  ) {

    memset( head , 0 , sizeof( head ) ) ;

    double l = inf , r = - inf ;

    scanf( "%d%d" , &n , &m ) ;

    while ( m -- ) {

        int s , t ; double d ; scanf( "%d%d%lf" , &s , &t , &d ) ;

        l = min( l , d ) , r = max( r , d ) ;

        AddEdge( s , t , d ) ;

    }

    while ( r - l > esp ) {

        double mid = ( l + r ) / 2.0 ;

        for ( int i = 0 ; i ++ < n ; ) {

            for ( edge *p = head[ i ] ; p ; p = p -> next ) {

                p -> d -= mid ;

            }

        }

        if ( check(  ) ) l = mid ; else r = mid ;

        for ( int i = 0 ; i ++ < n ; ) {

            for ( edge *p = head[ i ] ; p ; p = p -> next ) {

                p -> d += mid ;

            }

        }

    }

    printf( "%.8f\n" , l ) ;

    return 0 ;

}

相关文章

  • BZOJ-1486: [HNOI2009]最小圈(二分判定+DF

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1486 二...

  • 二分图

    二分图判定: 题目链接:二分图判定 dfs: 最大匹配: 题目链接:最大匹配-匈牙利算法 dfs: 二维最大匹配:...

  • 数据结构不难12

    题目1 : 二分图一•二分图判定 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 大...

  • 线性表查找

    【静态查找】 【二分查找判定树】 【1】判定树上每一个节点需要查找的次数刚好为该节点所在的层数;【2】查找成功时查...

  • 牛客bm101-二分查找/排序

    bm17 二分查找1,简单https://www.nowcoder.com/practice/d3df40bd23...

  • 二分法板子

    二分法常常使用,根据统计只用10%的程序员才可以完美写出二分,二分的关键在于对条件、边界的判定,而下面这个模板是一...

  • 2018-01-16笔记

    BDD BDD: 二叉判定图(二分决策图) 1.A new dynamic heuristic binary de...

  • 力扣 785 判断二分图

    题意:给定一堆graphes,判定他们是否是二分图 思路:遍历每一个二分图的节点,遍历的时候,检查相邻的两个节点不...

  • LA3177 长城守卫

    本篇博客侧重于贪心法正确性证明原问题可以二分答案转变为一个判定问题,该判定问题如下:有n个集合A1,A2,...,...

  • Python3机器学习实践:逻辑回归【实例:心脏病预测】

    逻辑回归的输出结果是判定二分类的,在实际问题中可用来解决二分类问题,当然也可利用多次的one****VS****o...

网友评论

    本文标题:BZOJ-1486: [HNOI2009]最小圈(二分判定+DF

    本文链接:https://www.haomeiwen.com/subject/mxnlzftx.html