【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;
}

posted @ 2016-09-30 21:58  _Mashiro  阅读(582)  评论(0编辑  收藏  举报