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