ZOJ Problem Set - 3946 Highway Project

题目链接

(堆优化的最短路)

题意:t组测试样例,每组样例先给出一行n m (表示0~n-1个点,m条边)随后给出m行边的信息,每行给出u , v ,t ,w (表示从u到v需要消耗t的时间和w的费用修路),问你每次都从0点开始去完所有点需要的最小时间是多少和所需要的修路费用,若是有多种答案输出修路费用最少的一组。

题解:(一开始没看样例又都错题,傻傻的看成了最小生成树了orz)因为它求的是每次从起点0出发一次去一个点,去完所有点的总时间,明显就是最短路(时间1e5不能暴力直接上一波模板)求最小时间,至于修路的费用,我们只需要把它加多一个条件(选取下一个要到达的点时在时间相同下先选修路费用最少的,改动一下优先队列比较即可)。

代码如下

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
#define ll long long
const int maxn = 1e5 + 500;
struct edge{//存边用于建图
	int  v;
	ll t, w;
	edge() {}
	edge(int vv,ll tt, ll ww){
		v = vv;
		t = tt;
		w = ww;
	}
};
struct node{//存点用与优先队列
	int  i;
	ll t, w;  //i=当前点,t=起点到当前点的最短时间,w=起点所在集合要到i点消耗的费用
	node() {}
	node( int ii,ll tt, ll ww){   
		i = ii;
		t = tt;
		w = ww;
	}
	bool operator <(const node &a)const{//按时间从小到大排,相同按费用小到大排
		if (a.t != t)
			return a.t < t;
		return a.w < w;
	}
};
vector<edge>g[maxn];
bool vis[maxn];
ll dis[maxn];   
int n, m;
void init() {
	for (int i = 0; i <= n; i++)
		g[i].clear(), vis[i] = false;
}
ll dijsktra(int s){//s为起点
	ll sum = 0;
	priority_queue<node>q;
	q.push(node(s, 0, 0));
	while (!q.empty()){
		node p = q.top();
		q.pop();
		if (vis[p.i]) continue;  //访问过跳过
		dis[p.i] = p.t;  //可以存到各个点的最短时间
		sum += p.w;
		vis[p.i] = true;
		for (int i = 0; i < g[p.i].size(); i++)
		{
			edge &e = g[p.i][i];
			if (vis[e.v]) continue;
			q.push(node(e.v, p.t + e.t, e.w));
		}
	}
	return sum;
}
int main(){
	int T, uu, vv;
	ll tt, ww;
	scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &m);
		init();
		while (m--)
		{
			scanf("%d%d%lld%lld", &uu, &vv, &tt, &ww);
			g[uu].push_back(edge(vv, tt, ww));
			g[vv].push_back(edge(uu, tt, ww));
		}
		ll ans2 = dijsktra(0);
		ll ans1 = 0;
		for (int i = 1; i < n; i++)
			ans1 += dis[i];
		printf("%lld %lld\n", ans1, ans2);
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_41156591/article/details/80091034