总结20220214

上午把dijkstra和floyd算法看懂了,用优化的dijkstra把题组刷完了,下午复习了一下最短路的代码,晚上答辩回答得不好,好多东西都学得不够深,有些会的也没讲好,看来知识学得太杂了,没梳理好,还要再多看看。

Heat Wave G

题目描述

有一个 nn 个点 mm 条边的无向图,请求出从 ss 到 tt 的最短路长度。

输入格式

第一行四个正整数 n,m,s,tn,m,s,t。 接下来 mm 行,每行三个正整数 u,v,wu,v,w,表示一条连接 u,vu,v,长为 ww 的边。

输出格式

输出一行一个整数,表示答案。

输入输出样例

输入 #1复制

7 11 5 4
2 4 2
1 4 3
7 2 2
3 4 3
5 7 5
7 3 3
6 1 1
6 3 4
2 4 3
5 6 3
7 2 1

输出 #1复制

7
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf = 2147483647;
const int N  = 1000000;
 
int n, m, Beg, End;
bool vis[N];
ll low[N];
 
// 链式前向星
struct node {
    ll to, next, v;
} edge[N];
int head[N];
int cnt = 0;
 
void add(int a, int b, int v) {
    cnt++;
    edge[cnt].v    = v;
    edge[cnt].to   = b;
    edge[cnt].next = head[a];
    head[a]        = cnt;
}
 
int Dij(int Beg,int End) {
    for (int i = 1; i <= n; i++) {
        low[i] = inf;
        vis[i] = false;
    }
    low[Beg] = 0;
    int idx  = Beg;
    while (true) {
        vis[idx] = true;
        for (int i = head[idx]; i != 0; i = edge[i].next) {
            int a = idx, b = edge[i].to, v = edge[i].v;
            if (!vis[b] && low[b] > low[a] + v) { low[b] = low[a] + v; }
        }
        ll Min = inf;
        for (int i = 1; i <= n; i++) {
            if (!vis[i] && Min > low[i]) {
                Min = low[i];
                idx = i;
            }
        }
        if (vis[idx]) break;
    }
    return low[End];
}
 
 
int main(int argc, char const *argv[]) {
    cin >> n >> m >> Beg >> End;
    for (int i = 1; i <= m; i++) {
        int a, b, v;
        cin >> a >> b >> v;
        add(a, b, v);
        add(b, a, v);
    }
    cout<<Dij(Beg,End);
    return 0;
}

单源最短路径(标准版)

题目背景

2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。

然后呢?

100 \rightarrow 60100→60;

\text{Ag} \rightarrow \text{Cu}Ag→Cu;

最终,他因此没能与理想的大学达成契约。

小 F 衷心祝愿大家不再重蹈覆辙。

题目描述

给定一个 nn 个点,mm 条有向边的带非负权图,请你计算从 ss 出发,到每个点的距离。

数据保证你能从 ss 出发到任意点。

输入格式

第一行为三个正整数 n, m, sn,m,s。 第二行起 mm 行,每行三个非负整数 u_i, v_i, w_iui​,vi​,wi​,表示从 u_iui​ 到 v_ivi​ 有一条权值为 w_iwi​ 的有向边。

输出格式

输出一行 nn 个空格分隔的非负整数,表示 ss 到每个点的距离。

输入输出样例

输入 #1复制

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

输出 #1复制

0 2 4 3
#include <bits/stdc++.h>
using namespace std;
const int N   = 100010;
const int inf = 2147483647;
const int M   = 500010;
 
int n, m, s;
int low[N];
int vis[N];
// 链式前向星
struct edge {
    int to, v, next;
} edge[M];
int head[N];
int cnt = 0;
 
// 重写优先队列
struct node {
    int idx;
    int v;
    bool operator<(const node &x) const { return x.v < v; }
};
// 链式前向星
void add(int a, int b, int c) {
    cnt++;
    edge[cnt].v    = c;
    edge[cnt].to   = b;
    edge[cnt].next = head[a];
    head[a]        = cnt;
}
// 初始化
void init() {
    for (int i = 1; i <= n; i++) {
        vis[i] = 0;
        low[i] = inf;
    }
}
 
// Dijkstra
void Dij() {
    low[s] = 0;
    priority_queue<node> q;
    // priority_queue<node> q;
    q.push({s, 0});
    while (q.size()) {
        int idx = q.top().idx;
        q.pop();
        if (vis[idx]) continue;
        vis[idx] = 1;
        for (int i = head[idx]; i; i = edge[i].next) {
            int a = idx, b = edge[i].to, v = edge[i].v;
            if (low[b] > low[a] + v) {
                low[b] = low[a] + v;
                if (!vis[b]) q.push({b, low[b]});
            }
        }
    }
    for(int i=1;i<=n;i++)
    cout << low[i] << ' ';
}
int main() {
    cin >> n >> m >> s ;
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
    }
    init();
    Dij();
    return 0;
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值