【LuoguP2792 】[JSOI2008]小店购物(最小树形图)
题目描述
小店的优惠方案十分简单有趣:
一次消费过程中,如您在本店购买了精制油的话,您购买香皂时就可以享受2.00元/块的优惠价;如果您在本店购买了香皂的话,您购买可乐时就可以享受1.50元/听的优惠价......诸如此类的优惠方案可概括为:如果您在本店购买了商品A的话,您就可以以P元/件的优惠价格购买商品B(购买的数量不限)。
有趣的是,你需要购买同样一些商品,由于不同的买卖顺序,老板可能会叫你付不同数量的钱。比如你需要一块香皂(原价2.50元)、一瓶精制油(原价10.00元)、一听可乐(原价1.80元),如果你按照可乐、精制油、香皂这样的顺序购买的话,老板会问你要13.80元;而如果你按照精制油、香皂、可乐这样的顺序购买的话,您只需付13.50元。
该处居民发现JSOI集训队的队员均擅长电脑程序设计,于是他们请集训队的队员编写一个程序:在告诉你该小店商品的原价,所有优惠方案及所需的商品后,计算至少需要花多少钱(不允许购买任何不必要的商品,即使这样做可能使花的钱更少)。
Sol
首先不用买的全部丢掉 , 优惠活动也不用管。
考虑一个最优策略 , 显然我们不会蠢到白白的优惠不要 , 那么一定是先所有要买的物品都买一个 , 然后就能取得所有优惠。直接取最小值当做价格即可。
那么问题就是让所有物品买一次后总价格最小。
这就很像一个生成树了。
由于有些物品可能没有优惠 , 我们建立一个超级点 , 向所有其他物品连原价的边 , 相当于买了超级点其他物品都能以原价的优惠购买。
这样就是要求一个以超级点为根的最小树形图了 , 朱刘算法即可。
简单说明朱刘算法的求解步骤:
首先要明确的一点是每一个点只会有一条入边。
- 为所有点找到一个最小的入边。
- 把这些边的权值加入答案 , 然后判断图中是否存在环。
- 不存在环那么算法结束 , 否则缩环(直接往入边方向跳即可,不要tarjan) , 并把所有不在环内边的边的权值减去指向点的最小入边(之前的环不合法 , 其中要去掉一条边 , 这里减去原入边边权就是在之后选择新的边的时候考虑了这个权值的变化)
本题code:
#include<bits/stdc++.h>
using namespace std;
typedef double db;
const int M=6000;
const int N=51;
struct edge{
int u,v;db val;
edge(){u=v=0,val=0.0;}
edge(int a,int b,db c){u=a,v=b,val=c;}
}a[M],b[M];
int In[N],vis[N],bel[N],cnt=0,m,n,bcc;
db cost[N];int ned[N];
db Mi[N];
int rt;db ans=0;
int flag=0;
bool MST(){
for(int i=1;i<=n;++i) In[i]=vis[i]=bel[i]=0;bcc=0,cnt=0;
for(int i=1;i<=m;++i) {
int u=a[i].u,v=a[i].v;db w=a[i].val;
if(!In[v]||a[In[v]].val>w) In[v]=i;
}
for(int i=flag;i<=n;++i) {
if(!flag&&!ned[i]) continue;
if(i!=rt) ans+=a[In[i]].val;
if(vis[i]) continue;
int u=i;
for(;u^rt&&vis[u]!=i&&!bel[u];u=a[In[u]].u) vis[u]=i;
if(u^rt&&!bel[u]) {
++bcc;while(bel[u]!=bcc) bel[u]=bcc,u=a[In[u]].u;
}
}
if(!bcc) return 0;
for(int i=flag;i<=n;++i) {
if(!flag&&!ned[i]&&i!=rt) continue;
if(!bel[i]) bel[i]=++bcc;
}
for(int i=1;i<=m;++i) {
int u=a[i].u,v=a[i].v;db w=a[i].val;
if(bel[u]==bel[v]) continue;
db goi=a[In[v]].val;b[++cnt]=(edge){bel[u],bel[v],w-goi};
}
for(int i=1;i<=cnt;++i) a[i]=b[i];
n=bcc;m=cnt;
return 1;
}
int main()
{
cin>>n;int tot=n;// !! 注意记录啊
for(int i=1;i<=n;++i) cin>>cost[i]>>ned[i],Mi[i]=cost[i];
cin>>m;
for(int i=1;i<=m;++i) {
int A,B;db P;
cin>>A>>B>>P;
if(!ned[A]||!ned[B]) --i,--m;
else {Mi[B]=min(Mi[B],P);a[i]=edge(A,B,P);}
}
for(int i=1;i<=n;++i) if(ned[i]) a[++m]=edge(0,i,cost[i]);
rt=0;flag=0;
while(MST()) rt=bel[rt],flag=1;
for(int i=1;i<=tot;++i) {
if(ned[i]) {
--ned[i];
ans+=Mi[i]*(db)ned[i];
}
}
printf("%.2lf\n",ans);
}
【LuoguP2792 】[JSOI2008]小店购物(最小树形图)的更多相关文章
- Luogu2792 JSOI2008 小店购物 最小树形图
传送门 被题意杀 本以为一个种类的物品一定要一起买 看了题解才知道可以先把所有要买的物品买一个,剩下要买的物品就可以得到这个种类的物品能够得到的最大优惠-- 所以现在只需要知道:第一次买所有物品一遍时 ...
- 洛谷P2792 [JSOI2008]小店购物(最小树形图)
题意 题目链接 Sol 一开始的思路:新建一个虚点向每个点连边,再加上题面中给出的边,边权均为大小*需要购买的数量 然后发现死活都过不去 看了题解才发现题目中有个细节--买了\(A\)就可以买\(B\ ...
- Luogu2792 [JSOI2008]小店购物
Luogu2792 [JSOI2008]小店购物 重题 bzoj4349 最小树形图 有 \(n\) 个物品,每个物品有价格 \(c_i\) 和所需个数 \(k_i\) ,所有物品必须恰好买 \(k_ ...
- [JSOI2008]小店购物 & bzoj4349:最小树形图 最小树形图
---题面(洛谷)--- ---题面(bzoj)--- 其实是同一道题,,,样例都一模一样 题解: 一开始看想了好久,,,还想到了最短路和最小生成树,,然而写的时候才意识到最小生成树应该要用无向边 其 ...
- JSOI2008 小店购物
https://www.luogu.org/problem/show?pid=2792 题目背景 JSOI集训队的队员发现,在他们经常活动的集训地,有一个小店因为其丰富的经营优惠方案深受附近居民的青睐 ...
- 最小树形图--朱刘算法([JSOI2008]小店购物)
题面 luogu Sol 首先设一个 \(0\) 号点,向所有点连边,表示初始价值 显然这个图的一个 \(0\) 为根的最小有向生成树的边权和就是每个买一次的最小价值 再买就一定能优惠(包含 \(0\ ...
- 【Bzoj2260】【Bzoj4349】商店购物 & 最小树形图
目录 List Bzoj 2260 商店购物 Description Input Output Sample Input Sample Output Bzoj 4349 最小树形图 Descripti ...
- bzoj2260: 商店购物 && 4349: 最小树形图
Description Grant是一个个体户老板,他经营的小店因为其丰富的优惠方案深受附近居民的青睐,生意红火.小店的优惠方案十分简单有趣.Grant规定:在一次消费过程中,如果您在本店购买了精制油 ...
- bzoj2260: 商店购物&&4349: 最小树形图
最小树形图问题啊 最小树形图是撒哩,就是给你一个有向图,确定一个根,要你到达所有点,那棵最短路径树的总边权 做这个用的是朱(jv)刘(lao)算法. 首先假如有多个联通块就无解啦 对应每个点(除了根) ...
随机推荐
- 用例a失败,跳过测试用例b和c并标记失败xfail
前言 当用例a失败的时候,如果用例b和用例c都是依赖于第一个用例的结果,那可以直接跳过用例b和c的测试,直接给他标记失败xfail用到的场景,登录是第一个用例,登录之后的操作b是第二个用例,登录之后操 ...
- oracle ogg--ogg搭建过程中遇到的错误及处理
1 PRVF-0002 : Could not retrieve local nodename---# Begin Stacktrace #---------------------------ID: ...
- Shiro 学习
<转载于 凯涛 博客> Shiro目录 第一章 Shiro简介 第二章 身份验证 第三章 授权 第四章 INI配置 第五章 编码/加密 第六章 Realm及相关对象 第七章 ...
- Jmeter---后置处理器 BeanShell PostProcessor 获取JDBC结果(多行)并以列表传入另一个请求
之前用python+locust对脚本生成商品编码, 商品上架,购买商品进行编写脚本和压测: 开始是打算用Jmeter,后来遇到问题在 Jmeter如何读取JDBC多行并组成列表,作为下一个请求 一直 ...
- 初学node.js-nodejs中实现删除用户路由
一.users_model.js 功能:定义用户对象模型 var mongoose=require('mongoose'), Schema=mongoose.Schema; var UserSche ...
- html5绘图笔记纪要
在html5之前,前端是无法再html页面上动态绘制图片 html5新增了一个canvas元素,相当于一个画布,可以获取一个CanvasRenderingContext2D对象 CanvasRende ...
- 手把手教你SOAP访问webservice并DOM解析返回的XML数据(转)
http://blog.csdn.net/u012534831/article/details/51357111 前言: 目前我们项目组还在采用webservice这种http方式,并且某些网站服务提 ...
- new 和 malloc 的区别 及使用
Malloc: 定义上:malloc memory allocation 动态内存分配 是c中的一个函数 使用方法: extern void *malloc(unsigned int num_byt ...
- Quartz-第三篇 quartz-misfire 错失,补偿执行
1.问题:使用pauseJob()后,再使用resumeJob(). Job如果中间时间足够短,默认会将之前错失的次数执行回来.这个问题的原因是执行调度策略的问题,quartz框架默认会将错失的执行次 ...
- 太原fpxt招标
5.31号13点多赶到太原,到yy公司,准备参加6.1号的jzfpxt投标,一起到yy山西分公司的还有北京yy总公司D工,Y工,W工等, D工负责标书及系统演示,我主要是根据D工的演示思路调整系统,演 ...