ACM图论基础算法概论
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for (i=1; i<n; i++) lowc[i] = cost[0][i];
for (i=1; i<n; i++) {
minc = inf; p = -1;
for (j=0; j<n; j++)
if (0 == vis[j] && minc > lowc[j]) {
minc = lowc[j]; wk.baidu.com = j;
struct edge {
int x, y, nxt; typec c; } bf[E];
void addedge(int x, int y, typec c) {
bf[ne].x = x; bf[ne].y = y; bf[ne].c = c; bf[ne].nxt = head[x]; head[x] = ne++; }
图论的基础算法小结
By yesterday @ BJTU
部分内容摘自HH的PPT
目录
图的存储 拓扑排序 最小生成树 最短路 强连通分量
图的存储——邻接矩阵
邻接矩阵
g[i][j] 表示顶点i和顶点j的边关系
是否有边相连 边权值
空间复杂度:O(n^2) 访问速度快、直观、适合稠密
return -1; }
void TopSort() {
for(int i = 0 ;i < n; ++ i) printf(“%d ” , Find());//输出拓扑排序结果
}
拓扑排序习题
校赛第四题(我没找到题号) 去年武汉区域赛第二题(可以到uva去刷
) Poj 1094(先用拓扑排序刷一下,等讲
拓扑排序的使用
判断一个有向图中是否有环。无环的图 所有点都能进行拓扑排序。
类似于课程安排问题的题目
拓扑排序代码示例
int Find()//找零入度点 {
for(int i = 0 ;i < n; ++ i) if(!Vis[i] && G[i]->degree == 0) { Vis[i] = 1; Grap *p = G[i]->next; while(p) {//更新其他节点 p->degree -- ; p = p->next; } return i; }
无向图O(4m+n) 对稀疏图可以减少存储空间 可以直接访问到一个点的相邻结点 图的信息一般都不做修改
图的存储方式—邻接表
邻接表使用场合
顶点数很多n>1000,边数却不多。
采用邻接表存储后,很多算法的复杂度也都 是跟边数有关。
连通性的问题很多情况边数不多,多采用邻 接表存储方式
邻接表code
int vis[V]; typec lowc[V];
typec prim(typec cost[][V], int n) // vertex: 0 ~ n-1
{
int i, j, p;
typec minc, res = 0;
memset(vis, 0, sizeof(vis));
vis[0] = 1;
了floyd,也可以试一下)
最小生成树
prim 算法(复杂度O(n^2) kruskal算法复杂度O(m*lg(m)) 对于不同问题可以选择不同算法
Prim 算法证明
首先,一定有一个最优解包含了权值最小的边e_1 (prim的第一步),因为如果不是这样,那么最优的 解不包含e_1,把e_1加进去会形成一个环,任意去掉 环里比e_1权值大的一条边,这样就构造了更优的一个 解,矛盾。
图的遍历方式
按照某种顺序访问图中的所有顶点, 这样的操作较遍历。常用的遍历方 式有: 深度优先遍历DFS 广度优先遍历BFS
拓扑排序
概念引入: 一个工程常被分为多个小的子工程,这 些子工程被称为活动(Activity),在有向 图中若以顶点表示活动,有向边表示活 动之间的先后关系,这样的图简称为 AOV网。在AOV网中为了更好地完成工程, 必须满足活动之间先后关系,需要将各 活动排一个先后次序即为拓扑排序。
用归纳法,假设prim的前k步选出来的边e_1,…, e_k是最优解的一部分,用类似的方法证明prim的方法 选出的e_k+1 一定也能构造出最优解
代码示例
#define typec int // type of cost
const typec inf = 0x3f3f3f3f; // max of cost
}
if (inf == minc) return -1; // 原图不连通
res += minc; vis[p] = 1;
for (j=0; j<n; j++)
if (0 == vis[j] && lowc[j] > cost[p][j])
lowc[j] = cost[p][j];
}
return res;
图的存储方式—邻接矩阵
邻接矩阵使用场合
数据规模不大n <= 1000,m越大越好 稠密图最好用邻接矩阵 图中不能有多重边出现 在做网络流类型的题目时候多采用邻接
矩阵,因为网络流的复杂度高,本身就 要求数据规模不能太大,并且需要频繁 地更新矩阵中的数据。
图的存储方式—邻接表
邻接表
mp[i]用链表的方式存储顶点i的相邻结点 空间复杂度:有向图O(2m+n)
}
克鲁斯卡尔算法
kruskal 算法思想:贪心选取最短的边来 组成一棵最小的生成树。
具体做法:先将所有的边做排序,然后 利用并查集作判断来优先选择较小的边, 直到建成一棵生成树。
克鲁斯卡尔算法示例代码(a)
struct Msg//定义边结构体 { int s , e; int length; }Line[6000]; int FindFather(int v)//并查集 { if(father[v] == v) return v; else father[v] = FindFather(father[v]); return father[v]; }
算法思想
1.从有向图中选取一个没有前驱的顶 点,并输出之;
2.从有向图中删去此顶点以及所有以 它为尾的弧;
重复上述两步,直至图空,或者图不 空但找不到无前驱的顶点为止。没有前 驱 -- 入度为零,删除顶点及以它为尾的 弧-- 弧头顶点的入度减1。
根据算法思想: 找到的点的顺序依次为v6 , v1 , v4 , v3 , v2 , v5 (注意一边输出当前点,一边更新其他点的入度)