图论模板
图论基础模板
Dijkstra
算法分析:
按路径长度递增次序产生算法:
把顶点集合V分成两组:
(1)S:已求出的顶点的集合(初始时只含有源点V0)
(2)V-S=T:尚未确定的顶点集合
将T中顶点按递增的次序加入到S中,保证:
(1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度
(2)每个顶点对应一个距离值
S中顶点:从V0到此顶点的长度。
T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度。
依据:V0到T中顶点Vk的,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和。
#include<bits/stdc++.h> #define N 100000 using namespace std; int a[N],f[N]; int n,m,ff,tt,cut; int h[N],ne[N],t[N],v[N]; void add(int f,int to,int vis){ne[++cut]=h[f],h[f]=cut,t[cut]=to,v[cut]=vis;} priority_queue<pair<int ,int >,vector<pair<int,int > >,greater<pair<int ,int > > >dl; void dij(int x) { dl.push(make_pair(0,x)); a[x]=0; while(dl.size()) { x=dl.top().second;dl.pop(); if(x==tt){cout<<a[tt];return;} if(f[x])continue;f[x]=1; for(int i=h[x];i;i=ne[i]) { int y=t[i]; if(a[x]+v[i]<a[y]){a[y]=a[x]+v[i];dl.push(make_pair(a[y],y));} } } } int main() { cin>>n>>m>>ff>>tt; memset(a,0x3f3f3f3f,sizeof(a)); for(int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z);add(y,x,z); } dij(ff); return 0; }
SPFA
LCA
fa[][]->f[][];
#include<bits/stdc++.h> #define N 500010 #define M 31 using namespace std; int f[N][M],lg[N],dept[N]; int head[N],to[N],net[N],cut; void add(int from,int t) { net[++cut]=head[from]; to[cut]=t; head[from]=cut; } void dfs(int fa,int x) { f[x][0]=fa; dept[x]=dept[fa]+1; for(int i=1;i<=lg[dept[x]];i++) f[x][i]=f[f[fa][i-1]][i-1]; for(int i=head[x];i;i=net[i]) if(to[i]!=fa)dfs(x,to[i]); } int lca(int x,int y) { if(x<y)swap(x,y); while(dept[x] > dept[y]) x = f[x][lg[dept[x]-dept[y]] - 1]; if(x==y)return x; for(int i=lg[dept[x]]-1;i>=0;i--) if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i]; return f[x][0]; } int main() { int n; cin>>n; for(int i=1;i<=n;i++) lg[i] = lg[i-1] + (1 << lg[i-1] == i); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(0,1); int k; cin>>k; for(int i=1;i<=k;i++) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } return 0; }