HDU-3790最短路径问题

题目

分析

先按距离求出最短路,再在最短路中找花费最小的路.
引申:多权最短路,在处理好主权的情况下,处理副权。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid  ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
	char c = getchar(),f = 1;x = 0;
	for(;c ^ '-' && !isdigit(c);c = getchar());
	if(c == '-') c = getchar(),f = -1;
	for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
	x *= f;
}
template<typename xxx>void print(xxx x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
const int maxn = 100010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
struct edge{
	int to,last,d,p;
}e[maxn<<1];
int head[maxn],tot;
inline void add(int from,int to,int d,int p) {
	++tot;
	e[tot].d = d;
	e[tot].p = p;
	e[tot].to = to;
	e[tot].last = head[from];
	head[from] = tot;
}
int n,m;
queue<int>q;
int dis[maxn],vis[maxn],num[maxn];
inline void spfa(int ks) {
	for(rint i = 0;i <= n; ++i) dis[i] = inf,vis[i] = 0,num[i] = 0;
	q.push(ks);dis[ks] = 0;num[ks] = 1;
	while(q.size()) {
		int x = q.front();q.pop();vis[x] = 0;
		for(rint i = head[x]; i; i = e[i].last) {
			if(dis[e[i].to] > dis[x] + e[i].d) {
				dis[e[i].to] = dis[x] + e[i].d;
				if(!vis[e[i].to]) {
					num[e[i].to] = 1;
					vis[e[i].to] = 1;
					q.push(e[i].to);
				}
			}
			else if(dis[e[i].to] == dis[x] + e[i].d) ++num[e[i].to];
		}
	}
}
int cost[maxn];
inline void ddfs(int ks) {
	for(rint i = 0;i <= n; ++i) vis[i] = 0,cost[i] = inf;
	q.push(ks);cost[ks] = 0;
	while(q.size()) {
		int x = q.front();q.pop();vis[x] = 0;
		for(rint i = head[x]; i; i = e[i].last) {
			if(dis[e[i].to] == dis[x] + e[i].d) {
				if(cost[e[i].to] > cost[x] + e[i].p) {
					cost[e[i].to] = cost[x] + e[i].p;
					if(!vis[e[i].to]) {
						vis[e[i].to] = 1;
						q.push(e[i].to);
					}
				}
			}
		}
	}
}
int main()
{
	while(1) {
		tot = 0;
		memset(head,0,sizeof(head));
		read(n);read(m);
		if(!n && !m ) break;
		for(rint i = 1;i <= m; ++i) {
			int a,b,c,d;
			read(a);read(b);read(c);read(d);
			if(a == b) continue;
			add(a,b,c,d);add(b,a,c,d);
		}
		int s,t;
		read(s);read(t);
		spfa(s);ddfs(s);
		print(dis[t]),putchar(' '),print(cost[t]),putchar('
');
	}
	return 0;
}
/*

*/

原文地址:https://www.cnblogs.com/Thomastine/p/11808652.html