CCF 201503-5 最小花费


在这里插入图片描述
在这里插入图片描述

总结:还需要优化,提交只能得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;
} 

提交结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值