AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 应用
  • 更多
    • 题解
    • 分享
    • 商店
    • 问答
  • 吐槽
  • 登录/注册

AcWing 342. $\Large\color{blue}{【算法提高课】道路与航线(\text{SPFA})}$    原题链接    中等

作者: 作者的头像   incra ,  2023-01-26 09:25:42 ,  所有人可见 ,  阅读 29


6


1

<—点个赞吧QwQ

宣传一下算法提高课整理

农夫约翰正在一个新的销售区域对他的牛奶销售方案进行调查。

他想把牛奶送到 $T$ 个城镇,编号为 $1 \sim T$。

这些城镇之间通过 $R$ 条道路 (编号为 $1$ 到 $R$) 和 $P$ 条航线 (编号为 $1$ 到 $P$) 连接。

每条道路 $i$ 或者航线 $i$ 连接城镇 $A_i$ 到 $B_i$,花费为 $C_i$。

对于道路,$0 \le C_i \le 10,000$;然而航线的花费很神奇,花费 $C_i$ 可能是负数($-10,000 \le C_i \le 10,000$)。

道路是双向的,可以从 $A_i$ 到 $B_i$,也可以从 $B_i$ 到 $A_i$,花费都是 $C_i$。

然而航线与之不同,只可以从 $A_i$ 到 $B_i$。

事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策:保证如果有一条航线可以从 $A_i$ 到 $B_i$,那么保证不可能通过一些道路和航线从 $B_i$ 回到 $A_i$。

由于约翰的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。

他想找到从发送中心城镇 $S$ 把奶牛送到每个城镇的最便宜的方案。

输入格式

第一行包含四个整数 $T,R,P,S$。

接下来 $R$ 行,每行包含三个整数(表示一个道路)$A_i,B_i,C_i$。

接下来 $P$ 行,每行包含三个整数(表示一条航线)$A_i,B_i,C_i$。

输出格式

第 $1..T$ 行:第 $i$ 行输出从 $S$ 到达城镇 $i$ 的最小花费,如果不存在,则输出 NO PATH。

数据范围

$1 \le T \le 25000$,
$1 \le R,P \le 50000$,
$1 \le A_i,B_i,S \le T$

输入样例:

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;
}

2 评论


用户头像
HUSTzyk   9天前      1    踩      回复

好哎!

用户头像
incra   9天前      1    踩      回复

thx


你确定删除吗?
1024
x

© 2018-2023 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息