zoukankan      html  css  js  c++  java
  • 【Bzoj2260】【Bzoj4349】商店购物 & 最小树形图

    Position:

    List

    目录

    Bzoj 2260 商店购物

    Description

      Grant是一个个体户老板,他经营的小店因为其丰富的优惠方案深受附近居民的青睐,生意红火。小店的优惠方案十分简单有趣。Grant规定:在一次消费过程中,如果您在本店购买了精制油的话,您购买香皂时就可以享受2.00元/块的优惠价;如果您在本店购买了香皂的话,您购买可乐时就可以享受1.50元/听的优惠价……诸如此类的优惠方案就是说:如果您在本店购买了商品A的话,您就可以以P元/件的优惠价格购买商品B(购买的数量不限)。有趣的是,你需要购买同样一些商品,由于不同的购买顺序,Grant老板可能会叫你付不同数量的钱。比如你需要一块香皂(原价2.50元)、一瓶精制油(原价10.00元)、一听可乐(原价1.80元),如果你按照可乐,精制油,香皂这样的顺序购买的话,Grant老板会问你要13.80元;而如果你按照精制油,香皂,可乐这样的顺序购买的话,您只需付13.50元。
    现在该村的居民请你编写一个程序,告诉你Grant小店商品的原价,所有优惠方案及所需的商品,计算至少需要花多少钱。不允许购买任何不需要的商品,即使这样做可能使花得钱更少。

    Input

    第一行为一个整数n(1 < =n < =50),表示Grant小店的商品种数。接下来是n行,其中第(i+1)行由一个实数Ci (0 < Ci < =1000)和一个整数Mi (0<=Mi<=100)组成,其间由一个空格分隔,分别表示第i种商品的原价和所需数量。第(n+2)行又是一个整数k,表示Grant小店的优惠方案总数。接着k行,每行有二个整数A,B(1 < =A,B < =n)和一个实数P(0 < =P < 1000),表示一种优惠方案,即如果您购买了商品A,您就可以以P元/件的优惠价格购买商品B,P小于商品B的原价。所有优惠方案的(A,B)都是不同的。为了方便,Grant不收分币,所以所有价格都不会出现分。

    Output

    只有一个实数,表示最少需要花多少钱。输出实数须保留两位小数。

    Sample Input

    4
    10.00 1
    1.80 1
    3.00 0
    2.50 2
    2
    1 4 2.00
    4 2 1.50

    Sample Output

    15.50

    Bzoj 4349 最小树形图

    Description

      小C现在正要攻打科学馆腹地------计算机第三机房。而信息组的同学们已经建好了一座座堡垒,准备迎战。小C作为一种高度智慧的可怕生物,早已对同学们的信息了如指掌。
    攻打每一个人的堡垒需要一个代价,而且必须攻打若干次才能把镇守之人灭得灰飞烟灭。
    当小C在绞尽脑汁想攻打方案时,突然从XXX的堡垒中滚出来一个纸条:一个惊人的秘密被小C发现了:原来各个堡垒之间会相互提供援助,但是当一个堡垒被攻打时,他对所援助的堡垒的援助就会停止,因为他自己已经自身难保了。也就是说,小C只要攻打某个堡垒一次之后,某些堡垒就只需要花更小的代价攻击了。
    现在,要你求消灭全机房要用掉代价最小多少。

    Input

    第一行一个数N,(N < =50),表示机房修建的堡垒数。
    接下来N行,每行两个数,第一个实数Ai表示攻打i号堡垒需要的代价Ai(0 < Ai < =1000)。第二个数Bi(0 < Bi < 100)表示i号堡垒需要被攻打Bi次。
    接下来一个数k,表示总共有k组依赖关系。
    接下来k行每行三个数x,y,z(x,y,为整数,z为实数),表示攻打过一次x号堡垒之后,攻打y号堡垒就只要花z的代价,保证z比y原来的代价小。
    不需要攻打的城堡不允许攻打。

    Output

    一行,一个实数表示消灭全机房要用的最小代价,保留两位小数。

    Sample Input

    4
    10.00 1
    1.80 1
    3.00 0
    2.50 2
    2
    1 4 2.00
    4 2 1.50

    Sample Output

    15.50

    CJ-test

    cjtest

    Solution

    乍看一眼这不都是一样的题吗?出题人就是这样,改个题面,就变了哦~多做题还是有好处的。
    以下Solution以CJ-test为准
    这个题对于每件物品只需要一件,那么对其它的影响就生效,并且每个买一件,那么接下来就可以用最小代价买剩下要买的物品。
    那么如何每个物品买一个?这里就要决定购买的顺序了。显然的最小树形图模板,不懂算法,传送门:Directed_MST 最小树形图

    Notice:

    1. 如果一个物品要买的数量为0,将其除去(为了算法的正常实行,可能图就不连通了)
    2. Combine时注意新权值减去的是之前标号的s[x]
    3. 注意自环的情况,见第一个break

    Code

    // <shopping.cpp> - Wed Sep 14 08:15:57 2016
    // This file is made by YJinpeng,created by XuYike's black technology automatically.
    // Copyright (C) 2016 ChangJun High School, Inc.
    // I don't know what this program is.
    
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #define MOD 1000000007
    using namespace std;
    typedef long long LL;
    const int MAXN=100010;
    const int MAXM=100010;
    inline int max(int &x,int &y) {return x>y?x:y;}
    inline int min(int &x,int &y) {return x<y?x:y;}
    inline int gi() {
    	register int w=0,q=0;register char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')q=1,ch=getchar();
    	while(ch>='0'&&ch<='9')w=w*10+ch-'0',ch=getchar();
    	return q?-w:w;
    }
    #define IN inline 
    #define RG register 
    struct Directed_MST{
        static const int N=110,M=N*N;
        static const double INF=1e9;
        int m,n,root;
        double w[M],s[N],ans,c[N];
        int u[M],v[M],pre[N],id[N],k[N],f[N];
        void Combine(){
            for(int i=1;i<=m;i++){
                int gg=v[i];u[i]=id[u[i]];v[i]=id[v[i]];
                if(u[i]!=v[i])w[i]-=s[gg];//gg is important
            }
        }
        void ZLEdmonds(){
            while(true){
                for(int i=1;i<=n;i++)s[i]=INF;
                for(int i=1;i<=m;i++)
                    if(w[i]<s[v[i]]&&u[i]!=v[i])s[v[i]]=w[i],pre[v[i]]=u[i];
                for(int i=1;i<=n;i++) {  
                    if(i == root) continue;  
                    if(s[i] == INF)    break;
                }  
                int cnt=1;
                memset(id,-1,sizeof(id));
                memset(f,0,sizeof(f));
                s[root]=0;
                for(int i=1;i<=n;i++){
                    ans+=s[i];int x=i;
                    while(f[x]!=i&&x!=root)
                        f[x]=i,x=pre[x];
                    if(x!=root&&id[x]==-1){
                        for(int o=pre[x];o!=x;o=pre[o])
                            id[o]=cnt;
                        id[x]=cnt++;
                    }
                }
                if(cnt==1)break;
                for(int i=1;i<=n;i++)if(id[i]==-1)id[i]=cnt++;
                Combine();n=cnt-1;root=id[root];
            }
            printf("%.2lf",ans);
        }
        void Work(){
            int cnt=gi();n=0;memset(id,0,sizeof(id));
            for(int i=1;i<=cnt;i++){
                scanf("%lf",&c[++n]);k[n]=gi()-1;
                if(k[n]<0){n--;continue;}id[i]=n;
            }
            m=ans=0;n++;root=n;int mm=gi();
            for(int i=1;i<n;i++)u[++m]=n,v[m]=i,w[m]=c[i];
            for(int i=1;i<=mm;i++){
                int x=gi(),y=gi();double p;scanf("%lf",&p);
                if(!(id[x]&&id[y]))continue;
                u[++m]=id[x];v[m]=id[y];w[m]=p;c[id[y]]=min(c[id[y]],p);
            }
            for(int i=1;i<n;i++)ans+=k[i]*c[i];
            ZLEdmonds();
        }
    }ZL;
    int main()
    {
    	freopen("shopping.in","r",stdin);
    	freopen("shopping.out","w",stdout);
        ZL.Work();
        return 0;
    }
    
    
  • 相关阅读:
    手机浏览器的viewport(视觉窗口)
    google开源了google chrome android
    Yii 直接执行SQL语句(转)
    WebKit学习网址收集
    Yii CDbCriteria的常用方法
    现货黄金入门知识普及一:图形分析之K线理论
    java 获取当前函数名
    yii url生成
    android 判断屏幕是否关闭
    yii yiiplayground
  • 原文地址:https://www.cnblogs.com/YJinpeng/p/5925027.html
Copyright © 2011-2022 走看看