upc/洛谷p1875--佳佳的魔法药水(最短路+图论模型转化)

题目大意:

给你n瓶药水,每个药水有一个权值p[i],你得到新的药水有两种方式
1.直接购买药水C
2.通过两个药水的合成 比如A+B=C
求得到药水0的最小花费和方案数

题解:

这个题求方案数可以想到类似最短路计数,那就需要把它转化成一个图的模型
如果dist[i]代表合成药水i的最低花费,那么如何更新dist[j]的最低花费
传统最短路都是从一个已经确定最短路的点出发,u->v 用u去更新v,这个题是两种药水合成一种药水
那么就从两个已经确定最短路的点出发 ,假如A+B合成C
就用dist[c] >dist[A]+dist[B] 更新
方案数就是最短路计数的模板了

有一个坑点就是 A+A=C的时候,存图的时候只要存一条边就可以了 (18分与100分的区别)

Code

int n,head[maxn],cnt,dist[maxn],vis[maxn],link[1600][1600],ans[maxn];
struct node {
    int u,v,w,next;
} e[maxn];
void add(int u,int v) {
    e[cnt].u=u,e[cnt].v=v;
    e[cnt].next=head[u],head[u]=cnt++;
}
void slove() {
    priority_queue<PII,vector<PII>,greater<PII> > q;
    rep(i,1,n) q.push({dist[i],i});
    while(q.size()) {
        PII fr= q.top();
        q.pop();
        int dian=fr.second;
        int dis=fr.first;
        if(vis[dian]) continue;
        vis[dian]=1;
        for(int i= head[dian]; ~i; i=e[i].next) {
            int v=e[i].v;
            int w = link[dian][v];
            if(vis[v]==0) continue;
            if(dist[w]>dis+dist[v]) {
                dist[w]=dis+dist[v];
                ans[w] = ans[v]*ans[dian];
                q.push({dist[w],w});
            } else if(dist[w]==dis+dist[v]) {
                ans[w]+=ans[v]*ans[dian];
            }
        }
    }
}
int  main() {
    n=read(),mst(head,-1);
    rep(i,1,n) dist[i]=read(),ans[i]=1;
    int u,v,w;
    while(cin>>u>>v>>w) {
        u++,v++,w++;
        add(u,v);
       if(u==v) continue;
        add(v,u);
        link[v][u]=w,link[u][v]=w;
    }
    slove();
    printf("%d %d",dist[1],ans[1]);
    return 0;

}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值