题目
\(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
#include
#include
#include
#include
#include
#include
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 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;
}
幸甚至哉,歌以咏志。