洛谷 P1875 佳佳的魔法药水
P1875 佳佳的魔法药水
https://www.luogu.com.cn/problem/P1875
题目背景
发完了
题目描述
存在 ab 相同 c 不同的情况,与题意相悖。题还是可以做,但数据待修正。
得到一种药水有两种方法:可以按照魔法书上的指导自己配置,也可以到魔法商店里去买——那里对于每种药水都有供应,虽然有可能价格很贵。在魔法书上有很多这样的记载:
-
最少花多少钱可以配制成功这种珍贵的药水;
-
共有多少种不同的花费最少的方案(两种可行的配置方案如果有任何一个步骤不同则视为不同的)。假定初始时你手中并没有任何可以用的药水。
输入格式
第一行有一个整数
第二行有
第三行开始,每行有三个整数 A、B、C,表示
输入以一个空行结束。
输出格式
输出两个用空格隔开的整数,分别表示得到
保证方案数不超过
输入输出样例 #1
输入 #1
7 10 5 6 3 2 2 3 1 2 0 4 5 1 3 6 2
输出 #1
10 3
说明/提示
数据范围:
每一种药水的价格均
样例说明:
最优方案有
- 直接买
号药水; - 买
号药水、 号药水配制成 号药水,直接买 号药水,然后配制成 号药水; - 买
号药水、 号药水配制成 号药水,买 号药水、 号药水配制成 号药水,然后配制成 号药水。
//这里没有固定的"源点",我可以定义一个数对,第一维存储某瓶药水的花费,第二维存储这个药水的编号,我一开始将所有{药水,药水编号}推入优先队列中, //然后根据这个最小的"药水花费"来更新别的药水,假设这里的药水为a,这里用出边来存储可以和a发生化学反应的药水b,用边权存储a和b可以获得的新药水c, //如果a和b加起来的花费<c,那么我可以更新c的最少价格为cost[a]+cost[b],且c的方案数为:ans[c]=ans[a]*ans[b]; //如果a和b加起来的花费==c,那么我更新c的方案数:ans[c]+=ans[a]*ans[b]; //这里我需要确保a和b的花费都是最小的,那么我可以使用vis数组打标记,如果a已经进行更新过了(即vis[a]===1),那么我就没有必要用a+别的药水--来更新新的药水 //如果a在枚举a的出边,也就是能和a发生化学反应的药水b的过程中,如果b的价格不是最小的(vis[b]!=1),那么我就没有必要用b+a来更新c... //这里的花费很像最短路中的"距离" #include<bits/stdc++.h> using namespace std; #define LL long long #define PLL pair<long,long> const int M=1e6+10; const int N=1e3+10; struct edge{ int v,w,ne; }; edge e[M]; bool vis[N]; //cost[i]代表药水i的最小花费,ans[i]表示得到药水i的最小花费的方案数 LL cost[N],ans[N],n; int idx,h[N],a,b,c; priority_queue<PLL,vector<PLL>,greater<PLL> > q; //存图 void add(int a,int b,int c){ e[idx]={b,c,h[a]}; h[a]=idx++; } void dijkstra(){ while(q.size()){ auto t=q.top();q.pop(); //当前花费最小的点 int u=t.second; //如果a更新过,那么再更新a就没有意义了.... if(vis[u]) continue; vis[u]=1; for(int i=h[u];~i;i=e[i].ne){ int v=e[i].v,w=e[i].w; //如果b没有被更新过,证明b药水现在还不是最小价格.....那么我使用b+a来更新c就没有意义了... if(vis[v]==0) continue; if(cost[w]>cost[u]+cost[v]){ cost[w]=cost[u]+cost[v]; ans[w]=ans[u]*ans[v]; //更新c药水的最低价格 q.push({cost[w],w}); } else if(cost[w]==cost[u]+cost[v]){ ans[w]+=ans[u]*ans[v]; } } } } int main() { cin>>n; fill(h,h+N,-1); for(int i=0;i<n;i++){ cin>>cost[i]; //先初始化为1,因为至少有一种方案 ans[i]=1; q.push({cost[i],i}); } while(cin>>a>>b>>c){ add(a,b,c); if (a == b) continue; add(b,a,c); } dijkstra(); cout<<cost[0]<<' '<<ans[0]<<'\n'; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现