BZOJ 2260 商店购物 & 4349 最小树形图

BZOJ 4349标题强行提示做法,样例和2260一样,出题人真是太懒了。。

发现对于某种物品,其购买量对方案是没有影响的,因此我们只考虑购买量为1的情况。建立虚点连向所有顶点,那么跑一次最小树形图即可。
另外购买量为0的点可以直接删了。

#include <cstdio>
#include <cstring>
#include <cmath>
#define ms(a,b) memset(a,b,sizeof(a))
#define FOR(i,j,k) for(int i=j;i<=k;++i)
const int N = 128, M = 10001;
void getmin(double &a, double b) { if (a > b) a = b; }
int u[M], v[M], id[N], vis[N], nav[N], count[N], fa[N];
double x[N], y[N], w[M], in[N], minc[N];
double edmonds(int rt, int n, int m) {
    int i, a, b, cnt;
    double ans = 0;
    while (1) {
        FOR(i,1,n) in[i] = 1e18;
        FOR(i,1,m) if (w[i] < in[v[i]] && u[i] != v[i])
            in[v[i]] = w[i], fa[v[i]] = u[i];
        FOR(i,1,n) if (i != rt && in[i] == 1e18) return -1;
        ms(id, 0); ms(vis, 0); in[rt] = 0; cnt = 0;
        FOR(i,1,n) {
            ans += in[i];
            for (b = i; vis[b] != i && !id[b] && b != rt; b = fa[b]) vis[b] = i;
            if (b != rt && !id[b]) {
                ++cnt;
                for (a = fa[b]; a != b; a = fa[a]) id[a] = cnt;
                id[b] = cnt;
            }
        }
        if (!cnt) break;
        FOR(i,1,n) if (!id[i]) id[i] = ++cnt;
        FOR(i,1,m) {
            int x = v[i];
            u[i] = id[u[i]]; v[i] = id[v[i]];
            if (u[i] != v[i]) w[i] -= in[x];
        }
        n = cnt; rt = id[rt];
    }
    return ans;
}


int main() {
    int n, i, k, a, b, m = 0, graph_node; double c;
    scanf("%d", &n);
    FOR(i,1,n) {
        scanf("%lf%d", &c, &count[i]);
        if (count[i]) ++m, v[m] = m; nav[i] = m; minc[m] = w[m] = c;
    }
    graph_node = m + 1; FOR(i,1,m) u[i] = graph_node;
    scanf("%d", &k);
    FOR(i,1,k) {
        scanf("%d%d%lf", &a, &b, &c);
        if (count[a] && count[b]) {
            u[++m] = nav[a], v[m] = nav[b];
            getmin(minc[v[m]], w[m] = c);
        }
    }
    double ans = edmonds(graph_node, graph_node, m);
    FOR(i,1,n) if(count[i] > 1) ans += (count[i] - 1) * minc[nav[i]];
    printf("%.2lf\n", ans);

    return 0;
}

2260: 商店购物

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 163 Solved: 45
[Submit][Status][Discuss]

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

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

4349: 最小树形图

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 52 Solved: 19
[Submit][Status][Discuss]

Description

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

Input

第一行一个数N,(N<=50),表示机房修建的堡垒数。
接下来N行,每行两个数,第一个实数Ai表示攻打i号堡垒需要的代价Ai(0

Output

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

Sample Input

3                                       
10.00  1
1.80  1 
2.50     2
2
1  3  2.00
3  2  1.50

Sample Output

15.50
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值