文章目录
前言
写于一只蹲在角落的蒟蒻-Z__X…
2020.2.7,图论和 d p dp dp 终于告一段落。蓦然回首,好似已走过许多…不曾细细品味,太多太多又绵延不断地向我涌来…
谨以此纪念 逝去 的图论和 d p dp dp;
图论
-
图的存储
首先,图论的基础:存储。这里介绍几种存储结构;
邻接矩阵
一种最简单,暴力的存储结构,二维数组存储;
注:这是读入方式的一种,具体看题目。
邻接表(链式前向星)cin >> n >> m; for (int i=1;i=m;i++) { cin >> i >> j >> x; a[i][j]=a[j][i]=x; }
邻接表,又叫链式前向星,其实就是链表的思路;
先开一个 l i n k k linkk linkk 数组, l i n k k [ i ] linkk[i] linkk[i] 表示的是以 i i i 为起点第一条边的编号, e e e 数组存边, e [ i ] . y e[i].y e[i].y 表示终点, e [ i ] . v e[i].v e[i].v 表示权值, e [ i ] . n e x t e[i].next e[i].next 表示下条边的编号;
邻接表核心就是一个插入函数:
还有一个循环同样重要,类似于查询:void insert(int x,int y,int v) //x为起点,y为终点,v为权值。 { e[++t].y=y; e[t].v=v; e[t].next=linkk[x]; linkk[x]=t; }
边表(边集数组)for (int i=linkk[x];i;i=e[i].next)
一种简便的存储结构,思路同样很简单,就是把所有的边存储到 e e e 数组中,要存储起点,终点,权值。struct node { int x,y; //起点和终点 int v; //权值 }e[maxm];
-
图的遍历
dfs遍历
邻接矩阵 d f s dfs dfs 遍历:
邻接表 d f s dfs dfs 遍历:void dfs(int k); { printf("%d",k); f[k]=true; for (int i=1;i<=n;i++) if (!f[i] && a[k][i]) dfs(i); }
bfs遍历void dfs(int k) { for (int i=linkk[k];i;i=e[i].next) if(!vis[e[i].y]) { vis[e[i].y]=1; dfs(e[i].y); } }
邻接矩阵 b f s bfs bfs 遍历:void bfs(int i); { memset(q,0,sizeof(q)); int head=1,tail=1; q[1]=i; f[i]=true; while (head<=tail) { k=q[head]; cout>>k; for (int j=1;j<=n,j++) if (a[k][j] && !f[j]) { q[++tail]=j; f[j]=true; } head++; } }
-
最短路
Floyd
以 k k k 为中转点,更新 i i i 到 j j j 的最短路
无向图优化版for (int k=1;k<=n;k++) for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (dis[i][k]+dis[k][j]<dis[i][j]) dis[i][j]=dis[i][k]+dis[k][j];
void Floyd() { for (int k