知识整理2019清北学堂提高储备D5

今天主讲图论。

前言:图的定义:图G是一个有序二元组(V,E),其中V称为顶集(Vertices Set),E称为边集(Edges set),E与V不相交。它们亦可写成V(G)和E(G)。

一、图的存储:

  1、邻接矩阵:

    

  2、邻接表:

    数组模拟链表实现:记录每条边的终点、边权(如果有的话)、同一起点的上一条边的编号,并记录以每个点为起点的最后一条边的编号。

    STL中的vector:记录以每个点为起点的边。

    

     一些vector的细节:

      vector 本质就是 c++ 模板库帮我们实现好的可以变长的数组

      向一个数组(vector型) a 的末尾加入一个元素 x a.push_back(x)
      询问 a 的长度 a.size(),询问a的真实长度a.capacity()
      注意:vector 中元素下标从 0 开始,当需要变长时,变长一倍,因此需要额外的内存空间。

      深入学习:https://www.cnblogs.com/zhonghuasong/p/5975979.html

    代码:

    邻接表:

const int N = 5005;//最多N个点/边struct edge {int u, v, w, next;//起点,终点,边权,同起点的上一条边的编号
}edg[N];
int head[N]; //以每个点为起点的最后一条边的编号
int  n, m, cnt; //cnt: 边的总数void add(int u, int v, int w)
{int e = ++cnt;edg[e] = (edge){u, v, w, head[u]};head[u] = e;
}
int main()
{cin >> n >> m; cnt = 0;for (int u, v, w, i = 1; i <= m; i++)cin >> u >> v >> w, add(u, v, w), odeg[u]++, ideg[v]++;return 0;
}

    vector:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int N = 5005;
 6 
 7 struct edge {
 8     int u, v, w;
 9 };
10 vector<edge> edg[N]; 
11 int  n, m, cnt; //cnt: numbers of edges
12 bool visited[N];
13 
14 void add(int u, int v, int w)
15 {
16     edg[u].push_back((edge){u, v, w});
17 }
18 void travel(int u, int distance)//遍历
19 {
20     cout << u << " " << distance << endl; visited[u] = true;
21     for (int e = 0; e < edg[u].size(); e++)
22         if (!visited[edg[u][e].v])
23             travel(edg[u][e].v, distance + edg[u][e].w); 
24 }
25 int main()
26 {
27     cin >> n >> m; cnt = 0;
28     for (int u, v, w, i = 1; i <= m; i++)
29         cin >> u >> v >> w, add(u, v, w);
30     return 0;
31 }
32         

二、生成树

       

  最小生成树:给定一个 n 个点 m 条边的带权无向图,求一个生成树,使得生成

树中边权和的最小。

  例题引入:

   

    扩展(引用百度百科):

  

     只要求出最小生成树就好了。

  求解最小生成树:

   生成树的本质:选取若干条边使得任意两点连通。

   各种求解算法的本质:贪心

   1、Kruskal算法(克鲁斯卡尔算法):

      将所有边按边权排好序,从最小的开始枚举:若加入该边后,会形成环(即边的端点已经连通),就忽略掉它,看下一条;否则加入该边,直至得到最小生成树(能得到的话)。查询两点连通情况:并查集。

    时间复杂度:O(E log E)

   代码:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1000005;
 6 struct edge {
 7     int u, v, w;
 8 }edg[maxn];
 9 int n, m, p[maxn], ans = 0;
10 
11 bool cmp(edge a, edge b)
12     {return a.w < b.w;}
13 int findp(int t) 
14     {return p[t] ? p[t] = findp(p[t]) : t;}
15 bool merge(int u, int v)
16 {
17     u = findp(u); v = findp(v);
18     if (u == v) return false;
19     p[u] = v; return true;
20 }
21 int main()
22 {
23     cin >> n >> m;
24     for (int i = 1, u, v, w; i <= m; i++)
25         cin >> u >> v >> w, edg[i] = (edge){u, v, w};
26     sort(edg + 1, edg + m + 1, cmp);
27     
28     for (int i = 1; i <= m; i++)
29         if (merge(edg[i].u, edg[i].v))
30             ans = max(ans, edg[i]. w);
31     cout << ans << endl;
32 }

  2、Prim算法(普里姆算法):

      以一点为最小生成树的根,找到一个到该最小连通块边权最小、不在该连通块里的点,并加入到该连通块,直到组成最小生成树。

    时间复杂度:O(n2)

    代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define forup(i,n) for(int i=1;i<=n;i++)//偷懒
using namespace std;
int n,m;
int ma[5001][5001],bianli=1,d[5001];
bool vis[5001];
int main()
{int x,y,z,tot=0;cin>>n>>m;memset(ma,0x3f,sizeof(ma));//求最短性图论问题一般初始化为一个很大的数
    forup(i,m){scanf("%d%d%d",&x,&y,&z);//去重边if(z<ma[x][y])ma[x][y]=ma[y][x]=z;}vis[1]=1;memset(d,0x3f,sizeof(d));d[1]=0;memset(vis,0,sizeof(vis));//0蓝1白 int stt_node,stt_dis;forup(i,n){stt_dis=0x3f3f3f3f,stt_node=0;for(int j=1;j<=n;j++)if(!vis[j]&&d[j]<stt_dis){stt_node=j;stt_dis=d[j];}vis[stt_node]=1;tot+=stt_dis;for(int j=1;j<=n;j++)if(!vis[j]&&d[j]>ma[j][stt_node]){d[j]=ma[j][stt_node];}}cout<<tot;return 0;
}

三、路径

   最短路径问题:

      

   

   最短路径算法本质思想:不断进行松弛操作(更新最短路操作)

   1、Floyd算法(弗洛伊德算法):

    

    正确性:

      

    可求任意两点之间的最短路(多源最短路),时间复杂度O(n);

   负权环:

    

    代码:

 1 int d[N][N], n, m;
 2 int main()
 3 {
 4     cin >> n >> m;
 5     for (int i = 1; i <= n; i++)
 6         for (int j = 1; j <= n; j++) d[i][j] = inf;
 7     for (int u, v, w, i = 1; i <= m; i++)
 8         cin >> u >> v >> w, d[u][v] = min(d[u][v], w);
 9 
10     for (int k = 1; k <= n; k++)
11         for (int i = 1; i <= n; i++)
12             for (int j = 1; j <= n; j++)
13                 d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
14 }

 

   2、Bellman-Ford算法(贝尔曼-福特算法)

    单源最短路算法,设源点为S

    

    正确性:

      d[u]至少经过1条边,经过几条边,用几条边松弛后就能得到真实值。任意最短路经过不超过 n − 1 条边,n 次松弛足矣。

   因此不适用于有负权环的情况。(n为点数,m为边数)

   易知Bellman-Ford 算法中,如果 d(u) 在上一次全局更新中没有被更新,那么这一次全局更新中不必松弛 u 的出边(若能更新,上一次就不会不更新)。

  代码:

 1 struct edge{
 2     int u, v, w;
 3 }edg[N];
 4 int d[N], n, m, S;
 5 int main()
 6 {
 7     cin >> n >> m >> S;
 8     for (int i = 1; i <= n; i++) d[i] = inf;
 9     for (int u, v, w, i = 1; i <= m; i++)
10         cin >> u >> v >> w, edg[i] = (edge){u, v, w};
11         
12     d[S] = 0;
13     for (int i = 1; i <= n; i++)
14         for (int j = 1; j <= m; j++)
15         {
16             int u = edg[j].u, v = edg[j].v, w = edg[j].w;
17             d[v] = min(d[v], d[u] + w);
18         }
19 }

 

   3.SPFA算法(Shortest Path Faster Algorithm 翻译:最短路径快速算法(在一般情况下的确挺快的,只要不被针对))

    贝尔曼-福特算法的队列优化形式,通过队列减少了很多冗余的计算,时间复杂度O(kE)(k是小常数,平均值为2)最糟糕的时间复杂度O(VE)(被针对的恐惧)  

    

    

    代码:

 1 struct edge{
 2     int u, v, w;
 3 };
 4 vector<edge> edg[N];
 5 int d[N], n, m, S;
 6 
 7 queue<int> Queue;
 8 bool inQueue[N];
 9 int cntQueue[N];
10 
11 void add(int u, int v, int w)
12 {
13     edg[u].push_back((edge){u, v, w});
14 }
15 int main()
16 {
17     cin >> n >> m >> S;
18     for (int i = 1; i <= n; i++) d[i] = inf;
19     for (int u, v, w, i = 1; i <= m; i++)
20         cin >> u >> v >> w, add(u, v, w);
21         
22     d[S] = 0; inQueue[S] = true; Queue.push(S);
23     while (!Queue.empty())
24     {
25         int u = Queue.front(); Queue.pop(); inQueue[u] = false;
26         for (int e = 0; e < edg[u].size(); e++)
27         {
28             int v = edg[u][e].v, w = edg[u][e].w;
29             if (d[v] > d[u] + w)
30             {
31                 d[v] = d[u] + w;
32                 if (!inQueue[v])
33                 {
34                     Queue.push(v); ++cntQueue[v]; inQueue[v] = true;
35                     if (cntQueue[v] >= n) {cout << "Negative Ring" << endl; return 0;}//是负权环 
36                 }
37             }
38         }
39     }
40     for (int i = 1; i <= n; i++)
41         cout << d[i] << endl;
42 }

 

   4.Dijkstra算法( 迪杰斯特拉算法)

      一个单源最短路算法。

      知道d(u) 被更新成真实值之前,u 出边的松弛操作都无意义。以一个点为源点,设d[i]为i节点到根的最短距离。将d初始化(有与源点连边的为边的边权,否则为很大的数),找到最小的d[i]且i未被确定,将i节点标记为已确定最短路,并更新i节点出边终点的d。重复以上过程至所有点都被确定。

      时间复杂度 O(n 2 + m)

      代码:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int N = 1e5 + 5;
 6 const int inf = 1 << 29;
 7 
 8 struct edge{
 9     int u, v, w;
10 };
11 vector<edge> edg[N];
12 int d[N], n, m, S;
13 
14 bool relaxed[N];
15 
16 void add(int u, int v, int w)
17 {
18     edg[u].push_back((edge){u, v, w});
19 }
20 int main()
21 {
22     cin >> n >> m >> S;
23     for (int i = 1; i <= n; i++) d[i] = inf;
24     for (int u, v, w, i = 1; i <= m; i++)
25         cin >> u >> v >> w, add(u, v, w);
26         
27     d[S] = 0;
28     for (int i = 1; i <= n; i++)
29     {
30         int u = 1; while (relaxed[u]) ++u;//找到第一个没有被确定的点 
31         for (int j = 1; j <= n; j++)//找到d[i]最短且未被确定的i 
32             if (!relaxed[j] && d[j] < d[u]) u = j; 
33         relaxed[u] = true;
34         for (int e = 0; e < edg[u].size(); e++)//进行松弛操作 
35         {
36             int v = edg[u][e].v, w = edg[u][e].w;
37             d[v] = min(d[v], d[u] + w);
38         }
39     }
40     for (int i = 1; i <= n; i++)
41         cout << d[i] << endl;
42 }

 

    EX:Dijkstra堆优化

   利用小根堆的性质节省找到d[i]最小且未被确定的i的时间。

  

   

    代码:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int N = 1e5 + 5;
 6 const int inf = 1 << 29;
 7 
 8 struct edge{
 9     int u, v, w;
10 };
11 vector<edge> edg[N];
12 int d[N], n, m, S;
13 
14 bool relaxed[N];
15 struct Qnode {
16     int u, du;
17     bool operator<(const Qnode &v)
18         const {return v.du < du;}//不加const会出错 
19 };
20 priority_queue<Qnode> PQueue;
21 
22 void add(int u, int v, int w)
23 {
24     edg[u].push_back((edge){u, v, w});
25 }
26 int main()
27 {
28     cin >> n >> m >> S;
29     for (int i = 1; i <= n; i++) d[i] = inf;
30     for (int u, v, w, i = 1; i <= m; i++)
31         cin >> u >> v >> w, add(u, v, w);
32         
33     d[S] = 0; PQueue.push((Qnode){S, 0});
34     while (!PQueue.empty())
35     {
36         int u = PQueue.top().u; PQueue.pop();
37         if (relaxed[u]) continue;
38             //if edges staring from u are already relaxed, no need to relax again.
39         relaxed[u] = true;
40         for (int e = 0; e < edg[u].size(); e++)
41         {
42             int v = edg[u][e].v, w = edg[u][e].w;
43             if (d[v] > d[u] + w)
44             {
45                 d[v] = d[u] + w;
46                 PQueue.push((Qnode){v, d[v]});
47                 //if d(v) is updated, push v into PQueue
48             }
49         }
50     }
51     for (int i = 1; i <= n; i++)
52         cout << d[i] << endl;
53 }

      

三、DAG(有向无环图)

  任意一个DAG一定有出度为0的点和入度为0的点。一个DAG删去一点后仍是DAG

  1、拓补排序(topsort)

    n个点的DAG一定存在拓补序列。

    按照有向图中边的起点一定在终点之前的顺序给出一个可行的节点序列(多数不唯一)

    换个角度:

    

   实现:

  1、

    找到 DAG 中入度为 0 的点 u,u 可以放在当前 DAG 拓扑序末尾将 v 和与 v 有关的连边从 DAG 中删除

  2、广搜:从入度为

 

 

 

  

 

  

 

 

    

 

 

 

      

      

转载于:https://www.cnblogs.com/InductiveSorting-QYF/p/10803250.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362902.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS之文字溢出处理

1.单行文本之三剑客<p>刘诗诗&#xff0c;原名刘诗施&#xff0c;1987年3月10日出生于北京市&#xff0c;中国内地影视女演员、影视出品人。</p>p{border: 1px solid red;width: 400px;height: 40px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis…

GA,RC,Alpha,Beta,Final等软件版本名词释义

对应上图的表格如下&#xff1a; 名词&#xff01;说明Alphaα是希腊字母的第一个&#xff0c;表示最早的版本&#xff0c;内部测试版&#xff0c;一般不向外部发布&#xff0c;bug会比较多&#xff0c;功能也不全&#xff0c;一般只有测试人员使用。Betaβ是希腊字母的第二个&…

HawtIO在JBoss EAP上(第二部分)

我刚刚发布了一篇关于在JBoss Wildfly 8.1上运行HawtIO的条目 。 从那篇文章中&#xff0c;您将了解HawtIO多么出色 &#xff0c;以及它必须具备的所有 出色 插件&#xff0c;才能从单个仪表板管理基于JVM的技术……好吧…… hawt ……。 但是&#xff0c;出于上一篇文章中概述…

Mule ESB,ActiveMQ和DLQ

在本文中&#xff0c;我将展示一个简单的Mule ESB流程&#xff0c;以了解实际中使用的Active MQ 的DLQ功能 。 我假设您有一个正在运行的Apache ActiveMQ实例&#xff08;如果没有&#xff0c;则可以在此处下载一个版本&#xff09;。 在此示例中&#xff0c;我使用了Mule ESB…

Choose and Divide UVa 10375

题目大意&#xff1a;给出p,q,r,s&#xff0c;求组合数C(p,q)/C(r,s) 题目思路&#xff1a; 化简得到&#xff1a;原式等价于(p!(r-s)!s!) / (r!(p-q)!q!) 由算数基本定理可知任意一个正整数可被唯一分解为素数幂乘积的形式&#xff0c;将分子分母分解后&#xff0c;进行约分即…

Linux sudo 详解

简单的说&#xff0c;sudo 是一种权限管理机制&#xff0c;管理员可以授权于一些普通用户去执行一些 root 执行的操作&#xff0c;而不需要知道 root 的密码。严谨些说&#xff0c;sudo 允许一个已授权用户以超级用户或者其它用户的角色运行一个命令。当然&#xff0c;能做什么…

echarts自定义图例legend文字和样式

话不多说&#xff0c;先上效果图。 要完成这个图并不难&#xff0c;主要是下面那个图例比较难&#xff0c;需要定制。 让我们从官方文档找找思路&#xff0c;官方文档关于legend.formatter是这样的&#xff1a;链接在这 难点在于&#xff1a; 1.这里的图例文本包含两个变量&am…

【题解】整理书本

题目描述 小A想把他满屋子的书整理一下。书本分成若干堆。每一堆的书本都有质量w和价值v。小A的任务是将所有书合成一堆。因为小A认为合并i&#xff0c;j两堆的书所需要的力为w[i]-v[i]w[j]-v[j]。合并后的书堆的质量和价值均为合并前两堆书的质量和价值的总和。也就是说&#…

JBoss Wildfly 8.1上的HawtIO

HawtIO为基于JVM的中间件提供了令人赞叹的视觉效果。 它是应用程序的统一控制台&#xff0c;否则将不得不构建自己的糟糕的Web控制台。 老实说&#xff0c;它们的构建方式各不相同&#xff0c;技术不同&#xff0c;用户体验不同&#xff0c;并且都围绕一种可怕的方式来尝试在QA…

jsp实现上一页下一页翻页功能

前段时间一直忙于期末考试和找实习&#xff0c;好久没写博客了。 这段时间做了个小项目&#xff0c;包含了翻页和富文本编辑器Ueditor的两个知识点,Ueditor玩的还不是很深&#xff0c;打算玩深后再写篇博客。 要实现翻页功能&#xff0c;只需要设置一个pageIndex即可&#xf…

自定义Cassandra数据类型

在博客文章《 从Java连接到Cassandra》中 &#xff0c;我提到了用Java 实现的Cassandra Java开发人员的一个优势是能够创建自定义 Cassandra数据类型 。 在这篇文章中&#xff0c;我将详细介绍如何执行此操作。 Cassandra具有许多内置的数据类型 &#xff0c;但是在某些情况下…

Docker的安装及注意事项

Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#…

基于CSS的个人网页

前端时间做的CSS作业&#xff1a;基于CSS的个人网页 基于CSS的个人网页 效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>吴广林的个人博客</title><link rel"styles…

Java验证(javafx)

验证是核心javafx框架所缺少的一件事。 为了填补这一空白&#xff0c; controlsfx中已经存在一个第三方验证库 。 但是&#xff0c;我有一个问题&#xff1a;它不是在考虑FXML的情况下创建的。 这并不是说它不是一个很好的库&#xff0c;只是错过了这个细节&#xff0c;对我来说…

WAP自助建站 我编程之路的启蒙

如题所示的这篇文章是我心血来潮在网上搜索到的&#xff0c;写的挺让我感同身受的&#xff0c;不妨先看一下原文吧。 原文 不知是偶然还是“冥冥定数”&#xff0c;最后一次访问娃派建站&#xff08;wap.ai&#xff09;已有数十月之久了&#xff0c;突然心血来潮想看看曾经的建…

初始socket模块和巧解粘包问题

1.什么是socket&#xff1f; 两个进程如果需要进行通讯最基本的一个前提能够唯一的标示一个进程&#xff0c;在本地进程通讯中我们可以使用PID来唯一标示一个进程&#xff0c;但PID只在本地唯一&#xff0c;网络中的两个进程PID冲突几率很大&#xff0c;这时候我们需要另辟它径…

webpack常用loader和plugin及打包速度优化

优化 或 也可以用&#xff1a; 备用&#xff1a; 慎用的配置&#xff0c;用的不好会增加打包时间&#xff1a; 代码丑化插件&#xff1a; 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com

react-native 热更新react-native-pushy集成遇到的问题

主要步骤按官方文档实现&#xff0c;这里只记录遇到的一些小坑 官方文档 run-android时NDK报错 前提是NDK已安装并且环境变量已设置 根据报错提示在 android/local.properties文件里加入ndk.dir~/Library/Android/android-ndk-r10e //这里改成你自己的ndk路径 cxxbridge找…

Keil5 仿真测试出现Cannot Load Flash Device Description 解决方法

1.用ST的烧录软件检测&#xff0c;可以烧录对应的Hex文件。 2.点击魔术棒&#xff0c;Debug选项卡检测芯片型号是否和当前芯片对应 3.在Flash Download选项卡中检查发现没有对应的芯片型号 4.点击Add 选项&#xff0c;选择对应的Flash类型如图&#xff1a; 添加Flash类型后&…

Hadoop—MapReducer统计文件的单词出现的个数

1. MapReduce 统计文件的单词出现的个数 Mapper: 处理具体文本&#xff0c;发送结果 Reducer: 合并各个Mapper发送过来的结果 Job: 制定相关配置&#xff0c;框架 Mapper package cn.itcast.hadoop.mr.wordcount;import java.io.IOException;import org.apache.hadoop.io.LongW…