【算法总结】图论相关

【最近公共祖先】

〖模板代码〗

[倍增算法]

 1 void dfs(int k)
 2 {
 3     for(int i=1;(1<<i)<=deep[k];i++)
 4         x[k][i]=x[x[k][i-1]][i-1];
 5     for(int i=head[k];i;i=e[i].next)
 6     {
 7         if(deep[e[i].to])continue;
 8         x[e[i].to][0]=k;
 9         deep[e[i].to]=deep[k]+1;
10         di[e[i].to]=di[k]+e[i].w;
11         dfs(e[i].to);
12     }
13 }
14 int lca(int ri,int rj)
15 {
16     if(deep[ri]<deep[rj])swap(ri,rj);
17     int d=deep[ri]-deep[rj];
18     for(int i=0;(1<<i)<=d;i++)
19         if((1<<i)&d)ri=x[ri][i];
20     if(ri==rj)return ri;
21     for(int i=16;i>=0;i--)
22         if((1<<i)<=deep[rj]&&x[ri][i]!=x[rj][i])
23             ri=x[ri][i],rj=x[rj][i];
24     return x[ri][0];
25 }

[树链剖分]

 1 void dfs1(int x)
 2 {
 3     sz[x]=1;
 4     for(int i=first[x];i;i=e[i].next)
 5     {
 6         int to=e[i].to;
 7         deep[to]=deep[x]+1;
 8         fa[to]=x;
 9         dfs1(to);sz[x]+=sz[to];
10         if(sz[to]>sz[son[x]])son[x]=to;
11     }
12 }
13 void dfs2(int x)
14 {
15     if(x==son[fa[x]])top[x]=top[fa[x]];
16     else top[x]=x;
17     for(int i=first[x];i;i=e[i].next)dfs2(e[i].to);
18 }
19 int lca(int x,int y)
20 {
21     for(;top[x]!=top[y];deep[top[x]]>deep[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
22     return deep[x]<deep[y]?x:y;
23 }

【网络流】

〖模板代码〗

[最小割]

 1 int cnt=1;
 2 void insert(int u,int v,int w)
 3 {
 4     e[++cnt]=(edge){v,first[u],w};first[u]=cnt;
 5     e[++cnt]=(edge){u,first[v],0};first[v]=cnt;
 6 }
 7 bool bfs()
 8 {
 9     memset(dis,-1,sizeof(dis));
10     int head=0,tail=1;
11     q[head]=S;dis[S]=0;
12     while(head!=tail)
13     {
14         int u=q[head++];
15         for(int i=first[u];i;i=e[i].next)
16         {
17             int v=e[i].to;
18             if(dis[v]!=-1||!e[i].flow)continue;
19             dis[v]=dis[u]+1;
20             q[tail++]=v;
21         }
22     }
23     return dis[T]!=-1;
24 }
25 int dfs(int u,int a)
26 {
27     if(u==T||a==0)return a;
28     int f,flow=0;
29     for(int& i=cur[u];i;i=e[i].next)
30     {
31         int v=e[i].to;
32         if(dis[v]==dis[u]+1&&(f=dfs(v,min(e[i].flow,a)))>0)
33         {
34             e[i].flow-=f;e[i^1].flow+=f;
35             flow+=f;a-=f;if(a==0)break;
36         }
37     }
38     return flow;
39 }
40 int main()
41 {
42     while(bfs())
43     {
44         for(int i=S;i<=T;i++)cur[i]=first[i];
45         ans+=dfs(S,inf);
46     }
47     return 0;
48 }

[最小费用最大流]

 1 bool spfa()
 2 {
 3     memset(inq,0,sizeof(inq));memset(dis,0x3f,sizeof(dis));
 4     int head=0,tail=1;q[0]=T;inq[T]=true;dis[T]=0;
 5     while(head!=tail)
 6     {
 7         u=q[head++];inq[u]=false;if(head>5000)head=0;
 8         for(int i=first[u];i;i=e[i].next)
 9         {
10             v=e[i].to;
11             if(e[i^1].flow>0&&dis[u]+e[i^1].cost<dis[v])
12             {
13                 dis[v]=dis[u]+e[i^1].cost;
14                 if(!inq[v])
15                 {
16                     if(dis[v]<dis[q[head]]){head--;if(head<0)head=5000;q[head]=v;}
17                     else{q[tail++]=v;if(tail>5000)tail=0;}
18                     inq[v]=true;
19                 }
20             }
21         }
22     }
23     return dis[S]<inf;
24 }
25 int dfs(int u,int a)
26 {
27     if(u==T||a==0)return a;
28     inq[u]=true;int f,flow=0;
29     for(int& i=cur[u];i;i=e[i].next)
30     {
31         v=e[i].to;
32         if(!inq[v]&&dis[u]==e[i].cost+dis[v]&&(f=dfs(v,min(e[i].flow,a)))>0)
33         {
34             e[i].flow-=f;e[i^1].flow+=f;
35             ans+=e[i].cost*f;flow+=f;a-=f;if(a==0)break;
36         }
37     }
38     return flow;
39 }

【二分图匹配】

〖模板代码〗

 1 int push(int x)
 2 {
 3     for(int i=1;i<=m;i++)
 4         if(!f[i]&&map[x][i])
 5         {
 6             f[i]=true;
 7             if(link[i]==-1||push(link[i]))
 8             {
 9                 link[i]=x;
10                 return 1;
11             }
12         }
13     return 0;
14 }

【最小生成树】

〖模板代码〗

 1 int find(int t){return f[t]==t?t:f[t]=find(f[t]);}
 2 int main()
 3 {
 4     n=read();m=read();
 5     for(int i=1;i<=n;i++)f[i]=i;
 6     for(int i=1;i<=m;i++)e[i].x=read(),e[i].y=read(),e[i].w=read();
 7     sort(e+1,e+m+1,cmp);
 8     for(int i=1;i<=m;i++)
 9     {
10         x=find(e[i].x);y=find(e[i].y);
11         if(x==y)continue;
12         f[x]=y;ans+=e[i].w;num++;
13         if(num==n-1)break;
14     }
15     if(num==n-1)printf("%d",ans);
16     else printf("-1");
17     return 0;
18 }

【最短路】

〖模板代码〗

 1 struct node{int id;LL d;bool operator <(const node& a)const{return d>a.d;}};
 2 priority_queue<node>q;
 3 void ins(int u,int v,int w){e[++cnt]=(edge){v,first[u],w};first[u]=cnt;}
 4 int main()
 5 {
 6     for(int i=1;i<=n;i++)dis[i]=inf;
 7     dis[S]=0;q.push((node){S,0});
 8     while(!q.empty())
 9     {
10         node t=q.top();q.pop();u=t.id;
11         if(dis[t.id]!=t.d)continue;
12         for(int i=first[u];i;i=e[i].next)
13             if(dis[e[i].to]>dis[u]+e[i].w)
14                 dis[e[i].to]=dis[u]+e[i].w,q.push((node){e[i].to,dis[e[i].to]});
15     }
16 }

原文地址:https://www.cnblogs.com/zsnuo/p/8886357.html

时间: 2024-09-30 12:58:51

【算法总结】图论相关的相关文章

N囚徒挑战——一个图论相关的概率问题

N囚徒挑战--一个图论相关的概率问题 一个房间内有 \(n\) 个盒子,从 \(1\) 到 \(n\) 编号.同时有 \(n\) 个从 \(1\) 到 \(n\) 的号码牌随机打乱放入盒子中,每个盒子有且仅有一个号码牌. 现有 \(n\) 个囚徒,从 \(1\) 到 \(n\) 编号.要求所有囚徒完成一项挑战,如果所有囚徒挑战成功,那么他们就会被释放.挑战内容是:每个囚徒依次进入房间,打开并查看任意数量不超过 \(\lfloor\frac{n}{2}\rfloor\) (向下取整)个的盒子内的号

玩转算法系列--图论精讲 面试升职必备(Java版)

第1章 和bobo老师一起,玩转图论算法欢迎大家来到我的新课程:<玩转图论算法>.在这个课程中,我们将一起完整学习图论领域的经典算法,培养大家的图论建模能力.通过这个课程的学习,你将能够真正地,玩转图论算法:) 第2章 图的基本表示千里之行,驶于足下.解决任何有一个图论算法问题,首先需要用基本的数据结构来表示图.在这一章,我们就将探索图的基本表示问题,学习邻接矩阵和邻接表,进而,也让同学们熟悉这个课程的整体代码风格. 第3章 图的深度优先遍历任何一种数据结构,都需要进行遍历.图也不例外.通过深

图论相关算法

转载自:http://cojs.tk/cogs/page/page.php?aid=30   最小生成树 Kruskal+ufs 1 int ufs(int x) { 2 return f[x] == x ? x : f[x] = ufs(f[x]); } int Kruskal() { 3 int w = 0; 4 for(int i=0; i<n; i++) 5 f[i] = i; 6 sort(e, e+n); 7 for(int i=0; i<n; i++) { 8 int x = u

算法—二叉查找树的相关一些操作及总结

二叉查找树得以广泛应用的一个重要原因就是它能够保持键的有序性,因此它可以作为实现有序符号表API中的众多方法的基础.这使得符号表的用例不仅能够通过键还能通过键的相对顺序来访问键值对.下面,我们要研究有序符号表API中各个方法的实现. 1.最大键和最小键 如果根结点的左链接为空,那么一棵二叉查找树中最小的键就是根结点:如果左链接非空,那么树中的最小键就是左子树中的最小键.简单的循环也能等价实现这段描述,但为了保持一致性我们使用了递归.找出最大键的方法也是类似的,只是变为查找右子树而已. 2.向上取

从存图到最短路算法的图论总结

INTRODUCTION: 图论算法在计算机科学中扮演着很重要的角色,它提供了对很多问题都有效的一种简单而系统的建模方式.很多问题都可以转化为图论问题,然后用图论的基本算法加以解决.--百度百科 对于OI而言,图是指由若干给定的点及若干条连接两点的线(边)所构成的图形 借助图论知识,我们往往可以将一些复杂的问题转化到基础的图论算法上,进而使用已有算法解决全新问题 那么想如果想要运用图论,首先要从存图开始 前排感谢教我图论的周润喵老师,syc学长,就序老师 可是我还是没学会 一,存图 对于一个图而

Prim算法和Kruskal算法(图论中的最小生成树算法)

最小生成树在一个图中可以有多个,但是如果一个图中边的权值互不相同的话,那么最小生成树只可能存在一个,用反证法很容易就证明出来了. 当然最小生成树也是一个图中包含所有节点的权值和最低的子图. 在一个图中权值最小的那个边一定在最小生成树中,如果一个图包含环,环中权值最大的边一定不在最小生成树中,还有就是连接图的任意两个划分的边中权值最短的那一条一定在最小生成树中. 下面介绍两个算法. Prim算法 Prim算法就是以任意一个点为源点,将所有点分为两组,一组是已经在最小生成树上的点,另一组是还未在最小

图像处理基本算法-卷积和相关

在执行线性空间滤波时,经常会遇到两个概念相关和卷积二者基本相似,在进行图像匹配是一个非常重要的方法.相关是滤波器模板移过图像并计算计算每个位置乘积之和的处理卷积的机理相似,但滤波器首先要旋转180度相关的计算步骤:(1)移动相关核的中心元素,使它位于输入图像待处理像素的正上方(2)将输入图像的像素值作为权重,乘以相关核(3)将上面各步得到的结果相加做为输出卷积的计算步骤:(1)卷积核绕自己的核心元素顺时针旋转180度(2)移动卷积核的中心元素,使它位于输入图像待处理像素的正上方(3)在旋转后的卷

【结论】图论相关结论

一.生成树相关 1.完全图生成树计数 n^n-2 2.左边n个点右边m个点的完全图生成树计数 (n^m-1)*(m^n-1) 3..... -- 原文地址:https://www.cnblogs.com/rir1715/p/8469405.html

算法——查找排序相关面试题和leetcode使用

1.给两个字符串s和t,判断t是否为s的重新排列后组成的单词. s = "anagram", t = "nagaram", return true. s = "rat", t = "car", return false. leetcode地址:https://leetcode.com/problems/valid-anagram/description/ (1)解法一:排序,O(n*logn) class Solution: