图论模板收录
这里主要收录一些与图论有关的模板
啊我还是太弱了居然要收录模板
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
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 }
4.Floyd求任意两点最短路
1 for(int i=1;i<=n;i++) 2 for(int j=1;j<=n;j++) 3 f[i][j]=INF; 4 for(int i=1;i<=n;i++) 5 f[i][i]=0; 6 for( int k=1;k<=n;k++) 7 for(int i=1;i<=n;i++) 8 for( int j=1;j<=n;j++) 9 if(f[i][k]+f[k][j]<f[i][j]) 10 f[i][j]=f[i][k]+f[k][j];
5.DIS分层图
数组开二维更好写一些~
而且好确定范围
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; const int M=1000200; int n,m,t,res,ans,cnt,num,k,root,end; int head[M]; int dis[M],vis[M]; struct node{ int dis; int pos; bool operator <(const node &x) const{ return dis>x.dis; } }s[M]; priority_queue <node> q; struct pp{ int u; int v; int nex; }e[5*M]; void add(int x,int y,int z){ e[++cnt].u=y; e[cnt].v=z; e[cnt].nex=head[x]; head[x]=cnt; } void di(){ dis[root]=0; q.push((node){0,root}); while(!q.empty()){ node tmp=q.top(); q.pop(); int x=tmp.pos; int d=tmp.dis; if(vis[x]) continue; vis[x]=1; for(int i=head[x];i;i=e[i].nex){ int y=e[i].u; if(dis[y]>dis[x]+e[i].v){ dis[y]=e[i].v+dis[x]; if(!vis[y]) q.push((node){dis[y],y}); } } } } int main(){ scanf("%d%d%d",&n,&m,&k); scanf("%d%d",&root,&end); for(int i=1;i<=m;i++) { int aa,bb,cc,dd; scanf("%d%d%d",&aa,&bb,&cc); add(aa,bb,cc);add(bb,aa,cc); for(int j=1;j<=k;j++){ add(n*j+aa,n*j+bb,cc); add(n*j+bb,n*j+aa,cc); add((j-1)*n+aa,j*n+bb,0); add((j-1)*n+bb,j*n+aa,0); } } memset(dis,0x3f,sizeof(dis)); di(); ans=dis[end]; for(int i=1;i<=k;i++){ ans=min(ans,dis[n*i+end]); } printf("%d",ans); return 0; }