BZOJ2260 商店購物 BZOJ4349 最小樹形圖 墜小樹形圖 朱劉算法

大家都很強, 可與之共勉 。

驚了,我以前朱劉算法的模板是錯的!!!!

題意:
  您要買n 種商品,每一種商品都有價格和需求量,有m 個優惠條件,以a,b,p 給出表示您買了a 商品之後b 商品的價格就會變成p ,(p< )。請問您賣完這些東西最少花費多少?
題解:

  墜小樹形圖,先跑出墜小樹形圖。確定每個東西買一個的最小總花費,然後所有東西一定可以以最小單價買到,累加就好了。
  板子不對TTTTTTTTTTTTTTTLE

雙倍經驗題 BZOJ4349

/**************************************************************
    Problem: 2260
    User: Lazer2001
    Language: C++
    Result: Accepted
    Time:16 ms
    Memory:7932 kb
****************************************************************/

# include <bits/stdc++.h>

const int N = 100010 ;

class DMST  {
    private :
        double in [N] ;
        int id [N], pre [N], vis [N] ;

        struct edge  {
            int u, v ; double c ;
        } g [N << 1] ;

        int ecnt ;

        inline double Zhuliu_algorithm ( int root, int n )  {
            double rt ( 0 ) ;
            register int i, u, v ;
            for ( ; ; )  {
                for ( i = 1 ; i <= n ; ++ i )  in [i] = 1e10 ;
                for ( i = 1 ; i <= ecnt ; ++ i )  {
                    u = g [i].u, v = g [i].v ;
                    if ( g [i].c < in [v] && ( u ^ v ) )  {
                        in [v] = g [i].c ;
                        pre [v] = u ;
                    }
                }
                for ( i = 1 ; i <= n ; ++ i )  {
                    if ( i != root && in [i] == 1e10 ) return -1 ;
                }
                int cnt ( 1 ) ;
                memset ( id, -1, sizeof ( int ) * ( n + 1 ) ) ;
                memset ( vis, -1, sizeof ( int ) * ( n + 1 ) ) ;
                in [root] = 0 ;
                for ( i = 1 ; i <= n ; ++ i )  {
                    rt += in [i] ;
                    int v = i ;
                    while ( vis [v] != i && id [v] == -1 && v != root )  {
                        vis [v] = i ;
                        v = pre [v] ;
                    }
                    if ( v != root && id [v] == -1 )  {
                        for ( u = pre [v] ; u != v; u = pre [u] )
                            id [u] = cnt ;
                        id [v] = cnt ++ ;
                    }   
                }
                if ( cnt == 1 ) return rt ;  //break ;
                for ( i = 1 ; i <= n ; ++ i )   if ( id [i] == -1 ) id [i] = cnt ++ ;
                for ( i = 1 ; i <= ecnt ; ++ i )  {
                    v = g [i].v ;
                    g [i].v = id [g [i].v] ;
                    g [i].u = id [g [i].u] ;
                    if ( g [i].u ^ g [i].v )  {
                        g [i].c -= in [v] ;
                    }
                }

                n = cnt - 1 ;
                root = id [root] ;
            }
        //  return rt ;
        }
    public :

        DMST ( )  { ecnt = 0 ; }

        inline void add_edge ( int u, int v, double w )  {
            g [++ ecnt] = ( edge )  {  u, v, w  } ;
        }

        inline double main ( int root, int n )  {
            return Zhuliu_algorithm ( root, n ) ;
        }
} T ;

double c [N] ;
int need [N] ;
int id [N] ;

int main ( )  {
    int n ;
    scanf ( "%d", & n ) ;
    int cnt ( 0 ) ;
    for ( int i = 1 ; i <= n ; ++ i )  {
        scanf ( "%lf%d", c + i, need + i ) ;
        if ( need [i] )  id [i] = ++ cnt ;
    }

    int root = cnt + 1 ; // cnt ;

    for ( int i = 1 ; i <= n ; ++ i )  if ( id [i] )  T.add_edge ( root, id [i], c [i] ) ; // c [i]...

    int k ;
    scanf ( "%d", & k ) ;
    while ( k -- )  {
        int u, v ; double cost ;
        scanf ( "%d%d%lf", & u, & v, & cost ) ;
        if ( ( ! id [u] ) || ( ! id [v] ) )  continue ;
        if ( cost < c [v] )  c [v] = cost ;
        T.add_edge ( id [u], id [v], cost ) ;
    }

    double ans = T.main ( root, cnt + 1 ) ;
    for ( int i = 1 ; i <= n ; ++ i )
        if ( need [i] > 1 )  {
            ans += 1.0 * ( need [i] - 1 ) * c [i] ;
        }

    printf ( "%.2lf\n", ans ) ;

    return 0 ;
}
發佈了223 篇原創文章 · 獲贊 38 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章