图论模板收录

泪湿孤枕 提交于 2019-11-28 16:02:09

这里主要收录一些与图论有关的模板

 啊我还是太弱了居然要收录模板 

 

1.链式向前星

 1 //链式向前星(数组模拟邻接表)
 2 //单向链表 
 3 struct pp
 4 {
 5     int s;//开始 (父亲) 
 6     int e;//结束 (儿子) 
 7     int v;//权值 
 8     int nex;
 9  } f[maxn];
10  int fir[maxn];
11 int main()
12 {
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++)//n条边 
15     {
16         scanf("%d",x,y,z);
17         f[i].s=x;
18         f[i].e=y;
19         f[i].v=z;
20         f[i].nex=fir[x];
21         fir[x]=i;
22     }
23     for(int i=fir[f];i;i=f[i].nex)
24         dfs;//遍历 
25 }
26 
27 //双向链表 
28 struct pp
29 {
30     int s;//开始 (父亲) 
31     int e;//结束 (儿子) 
32     int v;//权值 
33     int nex;
34  } f[maxn*2];
35  int fir[maxn];
36  int tot=0;
37  void build(int x,int y,int z) 
38 {
39     f[++tot].e=y; 
40     f[tot].s=x; 
41     f[tot].nex=fir[x];
42     f[tot].v=z;
43     fir[x]=tot;
44 }
45 //遍历,每个边遍历两次
46 int main()
47 {
48     scanf("%d",&n);//n条边 
49      for(int i=1;i<=n;i++)
50     {
51         int x,y,z;  scanf("%d%d%d",&x,&y,&z);
52         build(x,y,z); build(y,x,z);//来回时边权相同,不同的话循环n*2次依次输入 
53     }
54     for(int i=fir[f];i;i=f[i].nex)
55         dfs;
56      
57  } 
58  //树的遍历 ,只遍历一次(n个结点,n-1条边的全连通图叫树) 
59  void dfsl(int f,int fath)//现在的位置,父亲 
60 {
61     for(int i=fir[f];i;i=f[i].nex)
62       if(f[i].t!=fath)//遍历儿子结点并DFS 
63         dfsl(f[i].t,f);
64 }
65 int mian()
66 {
67     scanf("%d%d",&n,&s);//n个结点,s为根 
68     for(int i=1;i<=n-1;i++)
69     {
70         int x,y;  scanf("%d%d",&x,&y);
71         build(x,y); build(y,x);
72     }
73     dfsl(s,0);
74 }
链式向前星

 

2.LCA

 1 //LCA 
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<algorithm>
 7 using namespace std;
 8 const int maxn=500050;
 9 int tot,n,m,s;
10 struct pp
11 {
12     int t;
13     int nex;
14 }u[maxn*2];//邻接表(链式向前星)建图 
15 int fir[maxn],lg[maxn],fa[500001][22],dep[maxn];//邻接表(链式向前星)头数组,预处理 log_2(i)+1的值,fa[x][j]表示x的第2^j个祖先,深度 
16 void dfs(int f,int fath)//现在的位置,父亲 
17 {
18     dep[f]=dep[fath]+1;
19     fa[f][0]=fath;
20     for(int i=1;(1<<i)<=dep[f];i++) 
21       fa[f][i]=fa[fa[f][i-1]][i-1];//他的第2^i个祖先是他第2^(i-1)个祖先的第 2^(i-1)个祖先
22     for(int i=fir[f];i;i=u[i].nex)
23       if(u[i].t!=fath)//遍历儿子结点并DFS 
24         dfs(u[i].t,f);
25 }
26 int lca(int x,int y)
27 {
28     if(dep[x]<dep[y])//不妨假设x的深度更深 
29       swap(x,y);
30     while(dep[x]>dep[y])
31       x=fa[x][lg[dep[x]-dep[y]]-1];//先跳到同一高度 
32     if(x==y)
33       return x;
34     for(int k=lg[dep[x]]-1;k>=0;k--)
35       if(fa[x][k]!=fa[y][k])
36         x=fa[x][k], y=fa[y][k];//跳的LCA的儿子节点上 
37     return fa[x][0];//返回LCA 
38 }
39 void build(int x,int y) 
40 {
41     u[++tot].t=y; 
42     u[tot].nex=fir[x];
43     fir[x]=tot;
44 }
45 int main()
46 {
47     scanf("%d%d%d",&n,&m,&s);//n个结点,m次询问,s为根 
48     for(int i=1;i<=n-1;i++)
49     {
50         int x,y;  scanf("%d%d",&x,&y);
51         build(x,y); build(y,x);
52     }
53     dfs(s,0);
54 
55     for(int i=1;i<=n;i++)
56       lg[i]=lg[i-1]+(1<<lg[i-1]==i);//预处理,计算log_2(i)+1的值,用于优化常数 
57     for(int i=1;i<=m;i++)
58     {
59         int x,y;  scanf("%d%d",&x,&y);
60         printf("%d\n",lca(x,y));
61     }
62     return 0;
63 }
View Code

 

3.Kruskal求最小生成树

 1 #include<iostream>
 2 #include<cstdio> 
 3 #include<algorithm>
 4 using namespace std;
 5 int n,k,t,ans,cnt,res,m;
 6 struct pp
 7 {
 8     int u;
 9     int v;
10     int w;
11 }s[2000002];
12 int f[2000002],h[2000002];
13 int gf(int x)
14 {
15     if(f[x]==x) return x;
16     return f[x]=gf(f[x]);
17 }
18 bool cmp(pp x,pp y)
19 {
20     return x.w<y.w;
21 }
22 bool solve(int x,int y)
23 {
24     int t1=gf(x);int t2=gf(y);
25     if(t1!=t2)
26     {
27         f[t2]=t1;
28         return true;
29     }
30     return false;
31 }
32 int main()
33 {
34     scanf("%d%d",&n,&m);
35     for(int i=1;i<=n;i++)
36         f[i]=i;
37     for(int i=1;i<=m;i++)
38         scanf("%d%d%d",&s[i].u,&s[i].v,&s[i].w);
39     sort(s+1,s+1+m,cmp);
40     for(int i=1;i<=m;i++)
41     {
42         if(solve(s[i].u,s[i].v))
43         {
44             res++;
45             ans+=(res,s[i].w);//最小生成树的路径之和 
46         }
47         if(res==(n-1))
48         break;
49     }
50     cout<<ans;
51     return 0;
52 }
Kruskal

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!