总结:还需要优化,提交只能得30分。用的深度优先搜索的思想,思路很简单,就是在给定数据集的情况下怎么优化不超时比较难,谁有好的建议可以评论讨论。
思路
简单说下思路,由题意知输入的数据必然构成一棵树,所以就不用什么判断最短路径了,直接遍历节点,找到s到t的路径,逐渐更新过程中最小的单价,一直按照最小的单价购买食物。
技巧:这道题发现每两个城市之间只有唯一一条路径后思路就很明白了,因为题目说的n个城市有n-1条边,所以必然构成一棵树,一棵树里面任意两个节点的路径唯一。
所以代码比较简洁,但是性能有待优化。
实现代码
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
const int MAXN = 50010;
struct Node{
int v;
ll dis;
Node(int v,ll d):v(v),dis(d){};
};
struct c{
int u;
ll minw;
c(){};
c(int v,ll minw):u(v),minw(minw){};
};
vector<Node> Adj[MAXN];
bool inq[MAXN];
ll cost[MAXN];
ll minw;
ll a[MAXN] = {0};
queue<c> q;
void DFS(int s,int end){
while(!q.empty()){
c top = q.front(),temp;
q.pop();
int u = top.u;
temp.minw = min(a[u],top.minw);
for(int i = 0;i<Adj[u].size();i++){
int v = Adj[u][i].v;
ll dis = Adj[u][i].dis;
if(inq[v]) continue;
cost[v] = cost[u]+dis*temp.minw;
if(v==end) return;
if(!inq[v]){
temp.u = v;
q.push(temp);
inq[v] = true;
DFS(v,end);
}
}
}
}
int main(){
int n,m,u,v,s,t;
ll dis;
scanf("%d%d",&n,&m);
for(int i = 1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i = 0;i<n-1;i++){
scanf("%d%d%lld",&u,&v,&dis);
Adj[u].push_back(Node(v,dis));
Adj[v].push_back(Node(u,dis));
}
for(int i = 0;i<m;i++){
scanf("%d%d",&s,&t);
minw = a[s];
fill(cost,cost+MAXN,INF);
fill(inq,inq+MAXN,false);
cost[s] = 0;
while(!q.empty()) q.pop();
q.push(c(s,minw));
inq[s] = true;
DFS(s,t);
printf("%lld",cost[t]);
if(i!=m-1) printf("\n");
}
return 0;
}