图论

图论

本文将介绍DijkstraBellman-FordSPFAFloyd等算法

注意:本文图文并茂

将提供以下图文链接供大家理解:
图文链接:
飞书图解链接🎉🎉🎉
密码:L1@75666

1. Dijkstra算法

题目1

Acwing 849. Dijkstra求最短路 I

#include<bits/stdc++.h>
using namespace std;
const int N = 5e2 + 10, M = 1e5 + 10, INF = 0x3f3f3f3f;
int g[N][N], dist[N];
bool st[N];
int n, m;
int dijkstra(){
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
for(int i = 1; i < n; i ++ ){
int t = 0;
for(int j = 1; j <= n; j ++ ){
if(!st[j] && dist[t] > dist[j]) t = j;
}
for(int j = 1; j <= n; j ++ ){
if(dist[j] > dist[t] + g[t][j]){
dist[j] = dist[t] + g[t][j];
}
}
st[t] = true;
}
if(dist[n] == INF) return -1;
else return dist[n];
}
int main(){
memset(g, 0x3f, sizeof g);
scanf("%d%d", &n, &m);
int a, b, c;
while(m -- ){
scanf("%d%d%d", &a, &b, &c);
g[a][b] = min(g[a][b], c);
}
printf("%d\n", dijkstra());
for(int i = 0; i <= n; i ++ ){
printf("%s ", st[i] ? "true" : "false");
}
puts("");
return 0;
}

题目2

Luogu P3371 【模板】单源最短路径(弱化版)

#include<bits/stdc++.h>
using namespace std;
const int N = 1e4 + 10, M = 5e5 + 10, INF = INT_MAX;
struct edge{
int v, w;
};
int dist[N];
bool st[N];
vector<edge> e[N];
int n, m, s;
void dijkstra(int a){
for(int i = 0; i <= n; i ++ ) dist[i] = INF;
dist[a] = 0;
for(int i = 1; i < n; i ++ ){
int t = 0;
for(int j = 1; j <= n; j ++ ){
if(!st[j] && dist[t] > dist[j]) t = j;
}
st[t] = true;
for(auto &edge: e[t]){
int v = edge.v, w = edge.w;
if(dist[v] > dist[t] + w) dist[v] = dist[t] + w;
}
}
}
int main(){
scanf("%d%d%d", &n, &m, &s);
int a, b, c;
while(m -- ){
scanf("%d%d%d", &a, &b, &c);
e[a].push_back({b, c});
}
dijkstra(s);
for(int i = 1; i <= n; i ++ ){
printf("%d ", dist[i]);
}
return 0;
}

题目3

P4779 【模板】单源最短路径(标准版)

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 1e5 + 10, M = 2e5 + 10, INF = INT_MAX;
struct edge{
int v, w;
};
int dist[N];
bool st[N];
int n, m, s;
vector<edge> e[N];
priority_queue<PII, vector<PII>, greater<PII>> q;
void dijkstra(int s){
for(int i = 0; i <= n; i ++ ) dist[i] = INF;
dist[s] = 0;
q.push({0, s}); // PII = {dist, edge} edge 到点 s 的距离dist
while(q.size()){
auto t = q.top();
q.pop();
int u = t.second;
if(st[u]) continue;
st[u] = true;
for(auto &edge : e[u]){
int v = edge.v, w = edge.w;
if(dist[v] > dist[u] + w){
dist[v] = dist[u] + w;
q.push({dist[v], v});
}
}
}
}
int main(){
scanf("%d%d%d", &n, &m, &s);
int a, b, c;
while(m -- ){
scanf("%d%d%d", &a, &b, &c);
e[a].push_back({b, c});
}
dijkstra(s);
for(int i = 1; i <= n; i ++ ){
printf("%d ", dist[i]);
}
return 0;
}

题目4

AtCoder E - Skiing

题意如下:

E - 滑雪

AtCoder 滑雪场有N个开放区,分别是Space 1, Space 2,...,Space N. Space i 的海拔是Hi,有M个斜坡双向连接两个Space. 第i(1iM)个斜坡连接Space UiVi. 在任意两个空间之间使用一些斜坡是可能的。Takahashi仅通过斜坡从一个Space通过另一个Space. 每次通过一个斜坡他的幸福感改变. 具体地说,当他使用斜坡从Space X 到 Space Y,他的幸福感变化如下:

  • 如果Space X的海拔严格高于 Space Y,他的幸福感增加HXHY.
  • 如果Space X的海拔严格低于 Space Y,他的幸福感下降2×(HYHX).
  • 如果Space X的海拔等于 Space Y,他的幸福感不变.

幸福感可能是负值.
起初,Takahashi在Space 1,并且他的幸福感是0,找到他在通过任意数量(可能是0)的斜坡之后最大可能的幸福感,停止在任何Space.

数据范围:

  • 2N2×105
  • N1Mmin(2×105,N(N1)2)
  • 0Hi108(1iN)
  • 1Ui<ViN(1iM)
  • (Ui,Vi)(Uj,Vj)ifij
  • 输入的所有值是整数
  • 在任意两个Space之间使用一些斜坡是可能的(重边)。

输入:

N M
H1 H2 ... HN
U1 V1
U2 V2
.
.
.
UM VM

输出:
打印答案。

样例输入1:

4 4
10 8 12 5
1 2
1 3
2 3
3 4

样例输出1:

3

样例解释:

如果 Takahashi 从 Space 1 -> Space 3 -> Space 4,他的幸福感变化如下:

  • 当他从Space1(海拔10)到Space3(海拔12),他的幸福感下降2×(1210)=4,幸福感变为4.
  • 当他从Space3(海拔12)到Space4(海拔5)他的幸福感上升125=7,并且变为了(-4 + 7 = 3)

如果他结束滑雪,最终的幸福感是3,这是最大可能的值。

样例输入2:

2 1
0 10
1 2

样例输出2:

0

他一点不移动的幸福感最大。

题解如下

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = INT_MAX;
struct edge{
int v, w;
};
LL dist[N];
int h[N];
bool st[N];
int n, m;
vector<edge> e[N];
priority_queue<PII, vector<PII>, greater<PII>> q;
void dijkstra(int s){
for(int i = 0; i <= n; i ++ ) dist[i] = INF;
dist[s] = 0;
q.push({0, s}); // PII = {dist, edge} edge 到点 s 的距离dist
while(q.size()){
auto t = q.top();
q.pop();
int u = t.second;
if(st[u]) continue;
st[u] = true;
for(auto &edge : e[u]){
int v = edge.v, w = edge.w;
if(dist[v] > dist[u] + w){
dist[v] = dist[u] + w;
q.push({dist[v], v});
}
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++ ) scanf("%d", &h[i]);
int u, v;
while(m -- ){
scanf("%d%d", &u, &v);
if(h[u] > h[v]){ // h[u] > h[v]
e[u].push_back({v, 0});
e[v].push_back({u, h[u] - h[v]});
}else{ // h[v] > h[u]
e[v].push_back({u, 0});
e[u].push_back({v, h[v] - h[u]});
}
}
dijkstra(1);
LL ans = 0;
for(int i = 1; i <= n; i ++ ){
if(dist[i] == INF) continue;
ans = max(ans, -(dist[i] - h[1] + h[i]));
}
printf("%lld\n", ans);
return 0;
}

2. Bellman-Ford算法

题目1

Luogu P3385 【模板】负环

#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10, INF = 0x3f3f3f3f;
struct edge{
int v, w;
};
vector<vector<edge>> e(N);
int dist[N], cnt[N]; // cnt 表示点i距离远点的边数
bool st[N];
queue<int> q;
int T, n, m;
bool bellman_ford(int s){
memset(dist, 0x3f, sizeof dist);
dist[s] = 0;
bool flag; // 是否松弛
for(int i = 1; i <= n; i ++ ){
flag = false;
for(int u = 1; u <= n; u ++ ){
if(dist[u] == INF) continue;
for(auto const &edge : e[u]){
int v = edge.v, w = edge.w;
if(dist[v] > dist[u] + w){
dist[v] = dist[u] + w;
flag = true;
}
}
}
if(!flag) break;
}
return flag;
}
int main(){
scanf("%d", &T);
int a, b, c;
while(T -- ){
e.clear();
e.resize(N);
scanf("%d%d", &n, &m);
while(m -- ){
scanf("%d%d%d", &a, &b, &c);
if(c >= 0) e[b].push_back({a, c});
e[a].push_back({b, c});
}
printf("%s\n", bellman_ford(1) ? "YES" : "NO");
}
return 0;
}

3. SPFA算法

题目1

Luogu P3385 【模板】负环

#include<bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10, INF = 0x3f3f3f3f;
struct edge{
int v, w;
};
vector<vector<edge>> e;
int dist[N], cnt[N];
bool st[N];
queue<int> q;
int T, n, m;
bool spfa(int s){
memset(dist, 0x3f, sizeof dist);
dist[s] = 0;
st[s] = true;
q.push(s);
while(q.size()){
int u = q.front();
q.pop();
st[u] = false;
for(auto const &edge : e[u]){
int v = edge.v, w = edge.w;
if(dist[v] > dist[u] + w){
dist[v] = dist[u] + w;
cnt[v] = cnt[u] + 1;
if(cnt[v] >= n) return true;
if(!st[v]) q.push(v), st[v] = true;
}
}
}
return false;
}
int main(){
scanf("%d", &T);
while(T -- ){
e.clear();
e.resize(N);
// 清空 q
while(!q.empty()) q.pop();
memset(cnt, 0, sizeof cnt);
memset(st, 0, sizeof st);
scanf("%d%d", &n, &m);
int a, b, c;
while(m -- ){
scanf("%d%d%d", &a, &b, &c);
if(c >= 0) e[b].push_back({a, c});
e[a].push_back({b, c});
}
printf("%s\n", spfa(1) ? "YES" : "NO");
}
return 0;
}

题目2

TODO

4. Floyd算法

题目1

AcWing 854. Floyd求最短路

#include<bits/stdc++.h>
using namespace std;
const int N = 2e2 + 10, INF = 0x3f3f3f3f;
int g[N][N];
int n, m, q;
void floyd(){
for(int k = 1; k <= n; k ++ )
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= n; j ++ )
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
int main(){
scanf("%d%d%d", &n, &m, &q);
for(int i = 1; i <= n; i ++ ){
for(int j = 1; j <= n; j ++ ){
if(i == j) g[i][j] = 0;
else g[i][j] = INF;
}
}
int a, b, c;
while(m -- ){
scanf("%d%d%d", &a, &b, &c);
g[a][b] = min(g[a][b], c);
}
floyd();
while(q -- ){
scanf("%d%d", &a, &b);
if(g[a][b] > INF / 2) puts("impossible");
else printf("%d\n", g[a][b]);
}
return 0;
}

本文作者:爱情丶眨眼而去

本文链接:https://www.cnblogs.com/zshsboke/p/17905034.html

版权声明:本作品采用©️CC BY-NC-SA 4.0许可协议进行许可。

posted @   爱情丶眨眼而去  阅读(47)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑
  1. 1 赤伶 HITA
  2. 2 樱花树下的约定 (DJ-lucky小阳版) 旺仔小乔
  3. 3 踏雪 国风新语,Babystop_山竹
  4. 4 虞兮叹 闻人听書_
  5. 5 广寒宫 花沫
  6. 6 踏山河 七叔(叶泽浩)
  7. 7 破茧 张韶涵
  8. 8 下山 要不要买菜
  9. 9 红昭愿 音阙诗听
  10. 10 渡我不渡她 独孤
  11. 11 海草舞 陈冬霖
  12. 12 纸短情长 (女声版) 林玉冰
  13. 13 把梦照亮 赵小炮
  14. 14 沙漠骆驼 烟火兄弟
  15. 15 赢在江湖 姜鹏
  16. 16 孤勇者 杨宇峰
  17. 17 口是心非 张大帅
  18. 18 赐我 小时姑娘
  19. 19 囍(Chinese Wedding) 葛东琪
踏雪 - 国风新语,Babystop_山竹
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

踏雪 (国风新语原创企划《乐舞雅集》) - 国风新语/Babystop_山竹

词:烟十八

曲:董相麟@喜百音Hit Melody

编曲:浅逸

和声编唱:枕星烛

混音:啊鲤(龚骏混音工作室)

母带:龚骏

出品人:于明

统筹:唐潇/陈雅雪

发行:水星音乐

联合策划:国风新语

(未经著作权人许可,不得翻唱翻录或使用。)

冬风催 旧年岁 人未回

冬风催 旧年岁 人未回

望断千川只盼一个谁

几场喜悲 我颠沛

几场喜悲 我颠沛

一人空枕长夜难寐

一人空枕长夜难寐

红尘水 入酒杯 月下我饮醉

红尘水 入酒杯 月下我饮醉

大梦一场添几痕霜泪

风华已去 可曾悔

风华已去 可曾悔

儿女情长怎问错对

儿女情长怎问错对

我踏纷飞雪 听寒风冽冽

我踏纷飞雪 听寒风冽冽

转身挥剑 了断一腔眷恋

若往事如烟 飘荡山水间

若往事如烟 飘荡山水间

可否随风寄到你身边

我踏千秋雪 度似水流年

我踏千秋雪 度似水流年

无言冷月 听谁陈词唱遍

若情长半阙 爱该怎么写

若情长半阙 爱该怎么写

落笔你我不过伤离别

冬风催 旧年岁 人未回

冬风催 旧年岁 人未回

望断千川只盼一个谁

几场喜悲 我颠沛

几场喜悲 我颠沛

一人空枕长夜难寐

红尘水 入酒杯 月下我饮醉

红尘水 入酒杯 月下我饮醉

大梦一场添几痕霜泪

风华已去 可曾悔

风华已去 可曾悔

儿女情长怎问错对

儿女情长怎问错对

我踏纷飞雪 听寒风冽冽

我踏纷飞雪 听寒风冽冽

转身挥剑 了断一腔眷恋

若往事如烟 飘荡山水间

若往事如烟 飘荡山水间

可否随风寄到你身边

我踏千秋雪 度似水流年

我踏千秋雪 度似水流年

无言冷月 听谁陈词唱遍

无言冷月 听谁陈词唱遍

若情长半阙 爱该怎么写

若情长半阙 爱该怎么写

落笔你我不过伤离别

我踏纷飞雪 听寒风冽冽

我踏纷飞雪 听寒风冽冽

转身挥剑 了断一腔眷恋

转身挥剑 了断一腔眷恋

若往事如烟 飘荡山水间

若往事如烟 飘荡山水间

可否随风寄到你身边

我踏千秋雪 度似水流年

我踏千秋雪 度似水流年

无言冷月 听谁陈词唱遍

若情长半阙 爱该怎么写

落笔你我不过伤离别