这里主要收录一些与图论有关的模板
啊我还是太弱了居然要收录模板
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 }
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 }
