<—点个赞吧QwQ
宣传一下算法提高课整理{:target=”_blank”}
农夫约翰正在一个新的销售区域对他的牛奶销售方案进行调查。
他想把牛奶送到 T 个城镇,编号为 1simT。
这些城镇之间通过 R 条道路 (编号为 1 到 R) 和 P 条航线 (编号为 1 到 P) 连接。
每条道路 i 或者航线 i 连接城镇 Ai 到 Bi,花费为 Ci。
对于道路,0leCile10,000;然而航线的花费很神奇,花费 Ci 可能是负数(\-10,000leCile10,000)。
道路是双向的,可以从 Ai 到 Bi,也可以从 Bi 到 Ai,花费都是 Ci。
然而航线与之不同,只可以从 Ai 到 Bi。
事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策:保证如果有一条航线可以从 Ai 到 Bi,那么保证不可能通过一些道路和航线从 Bi 回到 Ai。
由于约翰的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。
他想找到从发送中心城镇 S 把奶牛送到每个城镇的最便宜的方案。
输入格式
第一行包含四个整数 T,R,P,S。
接下来 R 行,每行包含三个整数(表示一个道路)Ai,Bi,Ci。
接下来 P 行,每行包含三个整数(表示一条航线)Ai,Bi,Ci。
输出格式
第 1..T 行:第 i 行输出从 S 到达城镇 i 的最小花费,如果不存在,则输出 NO PATH
。
数据范围
1leTle25000,
1leR,Ple50000,
1leAi,Bi,SleT
输入样例:
6 3 3 4
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10
输出样例:
NO PATH
NO PATH
5
0
-95
-100
思路
氵题一道,在枚举边时注意判断即可。
代码
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
typedef pair<int,int> PII;
const int N = 1e6 + 10;
int h[N],e[N],ne[N],w[N],idx;
int h1[N],e1[N],ne1[N],idx1;
int dist[N];
bool v[N];
int T,R,P,S;
bool isValid (int a,int b) {
for(int i = h1[a];~i;i = ne[i]) {
if (e[i] == b) return false;
}
return true;
}
void add(int a,int b,int c) {
e[idx] = b;
ne[idx] = h[a];
w[idx] = c;
h[a] = idx++;
}
void add1 (int a,int b) {
e[idx] = b;
ne[idx] = h1[a];
h1[a] = idx++;
}
void spfa () {
memset(dist,0x3f,sizeof dist);
deque <int> q;
q.push_back (S);
dist[S] = 0;
v[S] = true;
while (q.size ()) {
int t = q.front ();
q.pop_front ();
v[t] = false;
for(int i = h[t];~i;i = ne[i]) {
int j = e[i];
if(isValid (t,j) && dist[j] > dist[t] + w[i]) {
dist[j] = dist[t] + w[i];
if(!v[j]) {
v[j] = true;
if (q.size () && dist[j] < dist[q.front()]) q.push_front (j);
else q.push_back (j);
}
}
}
}
return ;
}
int main() {
memset(h,-1,sizeof h);
memset(h1,-1,sizeof h1);
cin >> T >> R >> P >> S;
for (int i = 0;i < R;i++) {
int a,b,c;
cin >> a >> b >> c;
add(a,b,c),add(b,a,c);
}
for(int i = 0;i < P;i++) {
int a,b,c;
cin >> a >> b >> c;
add (a,b,c),add1(b,a);
}
spfa ();
for(int i = 1;i <= T;i++) {
if(dist[i] > 0x3f3f3f3f / 2) puts("NO PATH");
else cout << dist[i] << endl;
}
return 0;
}
好哎!
thx
isValid的优化逻辑是啥(蒟蒻发问
不是优化,是按照题目的要求去除不合法的边
难道这个政策不是题目保证的意思吗(
就是说题目保证没有负环而不是不合法。。。
这里是先加上然后删去非法的,这样方便
无脑测试过,不要这个判断也是可以的
啊?
怎么回事呢
你这里是优化过了吗 我写的spfa怎么一个也过不了
对,建议查一下SPFA的LLL,SLF优化
好,优化一般能把卡的点过过掉是吗
是的
比如有环的数据,把队列换成栈会快10倍(有一些题)
好的呢
朴素的SPFA也可以过14/16个点吧,最后两个点会TL
那可能是数据加强了,我也很久没看这题了