【笔记+模板】图论 持续更新中
来源:互联网 发布:android 5.1 数据开关 编辑:程序博客网 时间:2024/06/08 01:55
- 模板参见
- 存图
- 二分图判定
- 最短路
- 无权图
- 有权图
- Floyd 多源最短路
- SPFA优化的BF
- Dijkstras Algorithm
- 最小生成树
- kruskal算法
- prim
- 朴素prim堆优化prim和kruskal的算法效率实测
- 差分约束
模板参见
http://blog.csdn.net/loi_lxt/article/details/78249982
存图
//vector存图vector<int> tu[N],cost[N];void build(int f,int t,int v){ tu[f].push_back(t); cost[f].push_back(v); return ;}
//邻接表存图struct edge{ int f,t,v;}e[M];int next[M],first[N],tot;memset(first,-1,sizeof(first));void build(int f,int t,int v){ e[++tot]=(edge){f,t,v}; next[tot]=first[f]; first[f]=tot; return ;}
二分图判定
搜索,二分图染色
最短路
1.无权图
无权图:权值相等的图
bfs,dis=层数*权值;
2.有权图
Floyd 多源最短路
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
f[k][i][j]表示只经过1-k,i-j的最短距离;
SPFA(优化的BF)
可以处理负权,不能处理负环;
void spfa(int x){ dis[x]=0; while(!Q.empty()) Q.pop(); Q.push(x); inq[x]=1; while(!Q.empty()){ int u=Q.front(); Q.pop(); inq[u]=0; for(int i=first[u];i=-1;i=next[i]){ int v=e[i].t; if(dis[v]>dis[u]+e[i].v){ dis[v]=dis[u]+e[i].v; if(!inq[v]) Q.push(v),inq[v]=1; } } } return ;}
玄学优化:
1.改stl里的队列为栈,栈快一丢丢;
2.双端队列优化,对于要放入队列的v,将其的dis与队首的元素s的dis比较,
dis[v]大于dis[s] v放队尾;
dis[v]小于dis[s] v放队首;
stl里的双端队列慢且优化效果宣勋,慎重优化;
3.spfa_cy %%%%cy学长
Dijkstra’s Algorithm
基于贪心思想的最短路算法,不能处理负权;
struct node{ int x;int dis;};bool operator < (node a,node b){ return a.dis>b.dis;}priority_queue<node> Q;void dij(int x){ dis[x]=0; while(!Q.empty()) Q.pop(); Q.push((node){x,0}); while(!Q.empty()){ node u=Q.top();Q.pop(); if(used[u.x]) continue; used[u.x]=1; for(int i=0;i<tu[u.x].size();i++){ int v=tu[u.x][i]; if(dis[v]>dis[u.x]+cost[u.x][i]){ dis[v]=dis[u.x]+cost[u.x][i]; Q.push((node){v,dis[v]}); } } } return ;}
dij中,在元素x出堆的瞬间,x的最短路已经确定,所以可以得到终点最短路后直接返回;
dij的贪心证明
从起点到一个点的最短路径一定会经过至少一个“中转点”(把起点也看作一个中转点)
在求某点的最短路之前,它的中转点的最短路一定被确定了
堆中存的是待确定最短路的点即它们的某些状态,
取出堆中dis最小的点x,它的中转点的dis小于x的dis,所以它的中转点一定早于x被拿出堆;
那么x的中转点最短路已确定,x的dis是由确定最短路的点(包括中转点)更新来的,所以x的dis就是x的最短路。
证毕;
最小生成树
1.kruskal算法
主要运用了排序和并查集的思想;
将所有的边排序,按照权值从小到大依次尝试是否加入最小生成树中,
同时用并查集维护节点之间的联通关系
时间复杂度主要在 排序nlogn,因此不适用于稠密图
2.prim
百度百科的prim讲解超级棒
https://baike.baidu.com/item/Prim/10242166?fr=aladdin
算法流程(引自百度百科)
1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3).重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边< u , v >,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将 < u, v > 边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。
优化
prim算法在选取当前权值最小的边时,朴素算法需要枚举一遍,类似于迪杰斯特拉算法,我们可以用一个堆(优先队列)来将寻找的时间复杂度由O(n)降到O(logn)
3.朴素prim,堆优化prim和kruskal的算法效率实测
http://blog.csdn.net/gykimo/article/details/8538275
差分约束
详见
http://www.cppblog.com/menjitianya/archive/2015/11/19/212292.html
差分约束系统就是将一些系数为-1,1的不等式关系,转化为图上最长最短路问题,利用一系列最短路算法(或变形)求解的一类问题
需要注意的是
求最小值时,即给定一系列形如
b>=k1b>=k2b>=k3.....
的不等关系时,b的最小值为max{k},所以求的是最长路
将不等关系整理为下式,建图做最长路
d[v]>=d[u]+ < u,v >
求最大值时,
b<=k1b<=k2b<=k3.....
答案是min{k},求最短路
- 【笔记+模板】图论 持续更新中
- 比赛模板(持续更新中)
- 学习笔记,持续更新中
- hdu__KMP算法模板题【持续更新中】
- C++ 大数模板 持续更新中...
- [自用模板]持续更新!
- ACE学习笔记--持续更新中
- lua学习笔记(持续更新中)
- ACE学习笔记--持续更新中
- Sybase数据库学习笔记【持续更新中】
- python 学习笔记 持续更新中
- MongoDB学习笔记[持续更新中...]
- C++小笔记(持续更新中...)
- EnCache 学习笔记(持续更新中)
- android使用笔记 持续更新中。。。
- PRML学习笔记持续更新中~
- 天涯学习笔记(持续更新中。。。。)
- Hadoop学习笔记---持续更新中。。。
- 微信支付回调效验签名
- 快速排序
- 关于ANT指定系统工程编译JDK的设置
- 微信小程序中调用page中自定义的函数
- Vim配置
- 【笔记+模板】图论 持续更新中
- join()方法
- 频道管理
- STL-string的用法
- JS 阻止点击事件
- 通过 zxing 生成二维码
- MYSQL之union和order by分析([Err] 1221
- 子线程中Looper与Handler的使用
- 大数据准备-虚拟机安装之创建虚拟机(1)