【vijos】【树形dp】佳佳的魔法药水

描述

得到一种药水有两种方法:可以按照魔法书上的指导自己配置,也可以到魔法商店里去买——那里对于每种药水都有供应,虽然有可能价格很贵。在魔法书上有很多这样的记载:1份A药水混合1份B药水就可以得到1份C药水。(至于为什么1+1=1,因为……这是魔法世界)好了,现在你知道了需要得到某种药水,还知道所有可能涉及到的药水的价格以及魔法书上所有的配置方法,现在要问的就是:1.最少花多少钱可以配制成功这种珍贵的药水;2.共有多少种不同的花费最少的方案(两种可行的配置方案如果有任何一个步骤不同则视为不同的)。假定初始时你手中并没有任何可以用的药水。

格式

输入格式

第一行有一个整数N(N<=1000),表示一共涉及到的药水总数。药水从0~N-1顺序编号,0号药水就是最终要配制的药水。
第二行有N个整数,分别表示从0~N-1顺序编号的所有药水在魔法商店的价格(都表示1份的价格)。
第三行开始,每行有3个整数A、B、C,表示1份A药水混合1份B药水就可以得到1份C药水。注意,某两种特定的药水搭配如果能配成新药水的话,那么结果是唯一的。也就是说不会出现某两行的A、B相同但C不同的情况。

输出格式

输出两个用空格隔开的整数,分别表示得到0号药水的最小花费以及花费最少的方案的个数。

代码

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#define maxn 1100
using namespace std;

struct edge{
    int a,b; 
    edge(int a=0,int b=0){
        this->a=a; this->b=b;
    }
};

struct node{
    int num,dist;
    node(int num=0,int dist=0){
        this->num=num; this->dist=dist;
    }
};

bool operator < (const node &a,const node &b){
    if(a.dist==b.dist) return a.num>b.num; 
    else return a.dist>b.dist;
}

int n,c[maxn],dist[maxn],x,y,z,path[maxn];
vector<edge> g[maxn];
bool vis[maxn];

void dijkstra(){
    priority_queue<node> q;
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++){
        dist[i]=c[i];
        path[i]=1;
        q.push(node(i,dist[i]));
    }
    while(!q.empty()){
        int cur=q.top().num; q.pop(); 
        if(vis[cur]) continue;
        else vis[cur]=true;
        for(int i=0;i<(int)g[cur].size();i++){
            int a=g[cur][i].a,b=g[cur][i].b;
            if(vis[a]&&dist[b]>=dist[a]+dist[cur]){
                q.push(node(b,dist[b]));
                if(dist[b]==dist[a]+dist[cur]) path[b]+=path[a]*path[cur];
                else path[b]=path[a]*path[cur];
                dist[b]=dist[a]+dist[cur];
            }
        }
    }
}

int main(){
    //freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&c[i]);
    while(scanf("%d%d%d",&x,&y,&z)==3){
        g[x].push_back(edge(y,z));
        if(x!=y) g[y].push_back(edge(x,z));
    }
    dijkstra();
    printf("%d %d",dist[0],path[0]);
    return 0;
} 
原文地址:https://www.cnblogs.com/leotan0321/p/6081398.html