[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\n");
		else printf("%d\n",dis[i]);
	}
	return 0;
}

幸甚至哉,歌以咏志。

猜你喜欢

转载自www.cnblogs.com/DarthVictor/p/12804169.html