[USACO11JAN] Roads and Planes G

题目

(Farmer John)正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到(T)个城镇((1 <= T <= 25,000)),编号为(1)(T)。这些城镇之间通过(R)条道路((1 <= R <= 50,000),编号为(1)(R)) 和(P)条航线 ((1 <= P <= 50,000),编号为(1)(P)) 连接。每条道路(i)或者航线(i)连接城镇(A_i)((1 <= A_i <= T))到(B_i)((1 <= B_i <= T)),花费为(C_i)。对于道路,(0 <= C_i <= 10,000);然而航线的花费很神奇,花费(C_i)可能是负数((-10,000 <= C_i <= 10,000))。道路是双向的,可以从(A_i)(B_i),也可以从(B_i)(A_i),花费都是(C_i)。然而航线与之不同,只可以从(A_i)(B_i)。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策保证:如果有一条航线可以从(A_i)(B_i),那么保证不可能通过一些道路和航线从(B_i)回到(A_i)。由于(FJ)的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇(S(1 <= S <= T))把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。

Input

  • (1)行:四个空格隔开的整数:$ T, R, P,$and (S)

  • (2)(R+1)行:三个空格隔开的整数(表示一条道路):(A_i, B_i)(C_i)

  • (R+2)(R+P+1)行:三个空格隔开的整数(表示一条航线):(A_i, B_i)(C_i)

Output

  • (1)(T)行:从(S)到达城镇(i)的最小花费,如果不存在输出"NO PATH"。

Sample Input

6 3 3 4

1 2 5

3 4 5

5 6 10

3 5 -100

4 6 -100

1 3 -10

样例输入解释:

一共六个城镇。在(1-2,3-4,5-6)之间有道路,花费分别是(5,5,10)。同时有三条航线:(3->5,4->6)(1->3),花费分别是(-100,-100,-10)(FJ)的中心城镇在城镇(4)

Sample Output

NO PATH

NO PATH

5

0

-95

-100

样例输出解释:

(FJ)的奶牛从(4)号城镇开始,可以通过道路到达(3)号城镇。然后他们会通过航线达到(5)(6)号城镇。

但是不可能到达(1)(2)号城镇。

解说

幻影忍者前情提要: 这是一个勇敢的少年永不言弃地和时间抗争终于取得了胜利的故事。

首先看一眼题,这不就是很裸的最短路吗?有负边直接跑一遍(SPFA)就完了啊!而且题目保证了没有负环连判断都不用!

之后……(Vjudge)(T)掉了,洛谷(T)两个点……

[托腮][托腮]

有什么办法可以优化时间效率呢?

经过一番查找,我发现了一种叫做双向对列的优化方法。就是说,在把点入队的时候把目前的距离和队首元素比较一下,如果比队首元素大就推到队尾,否则放在队首,这样的话就可以尽量减少之后的点入队的次数从而达到优化效果。

现在结果如何?(Vjudge)成功卡过了,洛谷还是(T)了一个点。

[托腮][托腮]

再经过我一番查找,我又发现了一种叫做(inline)的东西,加在函数之前好像会快一点。讲解我看了半天没看懂……所以直接用了,然后就(A)了(我无话可说了)。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<string>
#include<queue>
using namespace std;
const int maxn=25000+3,maxe=150000+3,inf=1000000000;
int t,r,p,s,tot,head[maxn],dis[maxn],to[maxe],w[maxe],next[maxe];
bool vis[maxn];
deque<int> q;
void add(int a,int b,int l){
	w[++tot]=l;
	to[tot]=b;
	next[tot]=head[a];
	head[a]=tot;
}
inline void Spfa(int begin){
	for(int i=1;i<=t;i++) dis[i]=inf;
	dis[begin]=0,vis[begin]=1;
	q.push_back(begin);
	while(!q.empty()){
		int u=q.front();
		q.pop_front();
		vis[u]=0;
		for(int i=head[u];i;i=next[i]){
			int v=to[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				if(!vis[v]){
					if(!q.empty()&&dis[v]>=dis[q.front()]) q.push_back(v);
                    else q.push_front(v);
					vis[v]=1;
				}
			}
		}
	}
}

int main(){
	tot=1;
	scanf("%d%d%d%d",&t,&r,&p,&s); 
	int x,y,w;
	for(int i=1;i<=r;i++){	
		scanf("%d%d%d",&x,&y,&w);
		add(x,y,w);
		add(y,x,w);
	}
	for(int i=1;i<=p;i++){	
		scanf("%d%d%d",&x,&y,&w);
		add(x,y,w);
	}
	Spfa(s);
	for(int i=1;i<=t;i++){
		if(dis[i]==inf) printf("NO PATH
");
		else printf("%d
",dis[i]);
	}
	return 0;
}

幸甚至哉,歌以咏志。

原文地址:https://www.cnblogs.com/DarthVictor/p/12804169.html