最短路,最小生成树,及拓扑排序模板整理
来源:互联网 发布:linux查cpu核数 编辑:程序博客网 时间:2024/05/01 18:42
最短路,最小生成树,及拓扑排序都是图论基础算法,这里不再赘述,只进行模板整理,如有疑问还请评论留言
对于最短路算法,这里除常用的SPFA和堆优化Dijkstra外,还整理了许多学校和算法竞赛培训机构不会教授的Bellman_ford与原版Dijkstra,以便于读者理解前面的两种优化版本。
最短路:
最短路算法经典例题
http://codevs.cn/problem/1557/热浪
//Bellman_ford版本#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>const int INF=100000000; using namespace std;int t,c,ts,te,cnt;int u[100000],v[100000],d[100000],w[100000];void Bellman_ford(){ for(int i=1;i<=t;i++) d[i]=INF; d[ts]=0; for(int i=1;i<=t-1;i++) for(int j=1;j<=cnt;j++) { if(d[u[j]]<INF) d[v[j]]=min(d[v[j]],d[u[j]]+w[j]); }}int main(){ scanf("%d%d%d%d",&t,&c,&ts,&te); cnt=c; for(int i=1;i<=c;i++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); u[++cnt]=v[i]; v[cnt]=u[i]; w[cnt]=w[i]; } Bellman_ford(); printf("%d",d[te]); return 0;}
//SPFA邻接链表版本//SPFA是Bellman_ford的队列优化#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<queue>using namespace std;const int INF=1000000000;int t,c,ts,te,ru,rv,rw,tot,x;int d[100000],first[100000],next[100000];bool inq[100000];queue<int>q;struct Edge{ int u,v,w;}l[100000];void build(int u,int v,int w){ l[++tot]=(Edge){u,v,w}; next[tot]=first[u]; first[u]=tot;}void SPFA(){ for(int i=1;i<=t;i++) d[i]=INF; d[ts]=0; inq[ts]=1; q.push(ts); while(!q.empty()) { int k=q.front(); q.pop(); inq[k]=0; for(int i=first[k];i!=-1;i=next[i]) { x=l[i].v; if(d[k]<INF&&d[x]>d[k]+l[i].w) { d[x]=d[k]+l[i].w; if(!inq[x]) q.push(x); inq[x]=1; } } }}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d%d",&t,&c,&ts,&te); for(int i=1;i<=c;i++) { scanf("%d%d%d",&ru,&rv,&rw); build(ru,rv,rw); build(rv,ru,rw); } SPFA(); printf("%d",d[te]); return 0;}
//SPFA邻接表版本#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<queue>#include<vector>using namespace std;const int INF=1000000000;int t,c,ts,te,ru,rv,rw,tot,x,w;int d[100000];bool inq[100000];vector<int>G[100000];vector<int>V[100000];queue<int>q;inline void build(int u,int v,int w){ G[u].push_back(v); V[u].push_back(w); G[v].push_back(u); V[v].push_back(w);}void SPFA(){ for(int i=1;i<=t;i++) d[i]=INF; d[ts]=0; inq[ts]=1; q.push(ts); while(!q.empty()) { int k=q.front(); q.pop(); inq[k]=0; for(int i=0;i<G[k].size();i++) { x=G[k][i]; w=V[k][i]; if(d[k]<INF&&d[x]>d[k]+w) { d[x]=d[k]+w; if(!inq[x]) q.push(x); inq[x]=1; } } }}int main(){ scanf("%d%d%d%d",&t,&c,&ts,&te); for(int i=1;i<=c;i++) { scanf("%d%d%d",&ru,&rv,&rw); build(ru,rv,rw); } SPFA(); printf("%d",d[te]); return 0;}
//Dijkstra版本#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;const int INF=1000000000;int t,c,ts,te,x,y,r;int d[1000001];int w[2500][2500]; bool v[1000001];void dijkstra(){ for(int i=1;i<=t;i++) d[i]=INF; d[ts]=0; for(int i=1;i<=t;i++) { int k=0,m=INF; for(int j=1;j<=t;j++) { if(!v[j]&&d[j]<=m) { m=d[j]; k=j; } } v[k]=1; for(int j=1;j<=t;j++) if(!v[j]) d[j]=min(d[j],d[k]+w[k][j]); }}int main(){ scanf("%d%d%d%d",&t,&c,&ts,&te); for(int i=1;i<=t;i++) for(int j=1;j<=t;j++) { if(i!=j) w[i][j]=INF; } for(int i=1;i<=c;i++) { scanf("%d%d%d",&x,&y,&r); w[x][y]=w[y][x]=r; } dijkstra(); printf("%d",d[te]); return 0;}
//Dijkstra,堆优化,邻接链表版本#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int MAXN = 100000 + 5;int t,c,ts,te,tot,rs,re,rc;int dis[MAXN],first[MAXN],next[MAXN];bool done[MAXN];struct edge{ int f,t,v;}l[MAXN << 1];struct zt{ int num; int d;//距离用于排序 /*bool operator < (zt a)const { return d>a.d; } friend bool operator < (zt a,zt b) { return a.d<b.d; }*///2种写法,仅对结构体里的小于号生效}p[MAXN];priority_queue<zt>q;bool operator < (zt a,zt b){ return a.d>b.d;}void build(int f,int t,int v){ l[++tot]=(edge){f,t,v}; next[tot]=first[f]; first[f]=tot;}void dijkstra(){ while(!q.empty()) q.pop(); q.push((zt){ts,0}); dis[ts]=0; while(!q.empty()) { zt a=q.top(); int u=a.num; q.pop(); if(done[u]==1) continue; done[u]=1; for(int i=first[u];i!=-1;i=next[i]) { int v=l[i].t; if(dis[v]>dis[u]+l[i].v) { dis[v]=dis[u]+l[i].v; q.push((zt){v,dis[v]}); } } }}int main(){ memset(dis,0x3f,sizeof(dis)); memset(first,-1,sizeof(first)); scanf("%d%d%d%d",&t,&c,&ts,&te); for(int i=1;i<=c;i++) { scanf("%d%d%d",&rs,&re,&rc); build(rs,re,rc); build(re,rs,rc); } dijkstra(); printf("%d",dis[te]); return 0;}
http://codevs.cn/problem/1021/玛丽卡
对答案有贡献的路径只存在于最短路上
先跑一边SPFA找出最短路上的边,依次尝试删除每条边,跑SPFA统计答案即可
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>using namespace std;const int INF = 1000000007;int n,m,ru,rv,rw,tot,ans;int dis[500010],first[1000010],nxt[1000010],pre[500010];bool flag;bool inq[100010];struct edge{ int u,v,w;}l[1000010];queue<int>q;void build(int f,int t,int c){ l[++tot]=(edge){f,t,c}; nxt[tot]=first[f]; first[f]=tot;}void SPFA(int l1,int l2){ for(int i=1;i<=n;i++) dis[i]=INF; dis[1]=0; q.push(1); inq[1]=1; while(!q.empty()) { int k=q.front(); q.pop(); inq[k]=0; for(int i=first[k];i!=-1;i=nxt[i]) { int x=l[i].v; if((k==l1&&x==l2)||(k==l2&&x==l1)) continue; if(dis[x]>dis[k]+l[i].w) { dis[x]=dis[k]+l[i].w; if(!flag) pre[x]=k; if(!inq[x]) { q.push(x); inq[x]=1; } } } }}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&ru,&rv,&rw); build(ru,rv,rw); build(rv,ru,rw); } tot=0; SPFA(0,0); flag=1; for(int i=n;i;i=pre[i]) { SPFA(i,pre[i]); ans=max(ans,dis[n]); } printf("%d",ans); return 0;}
最小生成树:
http://codevs.cn/problem/1231/最优布线问题
//Kruskal版本#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>using namespace std;typedef unsigned long long LL;int n,m,cnt,x,y,e;int u[1000000],v[1000000],w[1000000],r[1000000],fa[1000000];LL cost;bool cmp(int a,int b){ return w[a]<w[b];}int find(int x){ return fa[x]==x?x:fa[x]=find(fa[x]);}void kruskal(){ for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) r[i]=i; sort(r+1,r+m+1,cmp); for(int i=1;i<=m;i++) { e=r[i]; x=find(u[e]); y=find(v[e]); if(x!=y) { cost+=w[e]; fa[x]=y; } }}int main(){ scanf("%d%d",&n,&m); cnt=n; for(int i=1;i<=m;i++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); } kruskal(); printf("%lld",cost); return 0;}
//Prim#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#include<queue>using namespace std;typedef unsigned long long LL;const int MAXN=1000000;LL n,m,rf,rt,rv,tot,cost,cnt;LL first[MAXN],next[MAXN];bool done[MAXN];struct Edge{ LL f,t,v;}l[MAXN];struct condition { LL num,d;}p[MAXN];priority_queue<condition>q;bool operator < (condition a,condition b){ return a.d>b.d;}void build(int f,int t,int v){ l[++tot]=(Edge){f,t,v}; next[tot]=first[f]; first[f]=tot;}void prim(){ while(!q.empty()) q.pop(); q.push((condition){1,0}); while(!q.empty()&&cnt<n) { condition a=q.top(); LL u=a.num; LL w=a.d; q.pop(); if(done[u]) continue; done[u]=1; cost+=w; cnt++; for(int i=first[u];i!=-1;i=next[i]) if(!done[l[i].t]) q.push((condition){l[i].t,l[i].v}); }}int main(){ memset(first,-1,sizeof(first)); scanf("%lld%lld",&n,&m); for(int i=1;i<=m;i++) { scanf("%lld%lld%lld",&rf,&rt,&rv); build(rf,rt,rv); build(rt,rf,rv); } prim(); printf("%lld",cost); return 0;}
拓扑排序:
http://codevs.cn/problem/2833/奇怪的梦境
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>using namespace std;queue<int>q;int n,m,ru,rv,tot,cnt,fla;int first[100001],next[100001],pas[100001],ans[100001],jud1[100001],jud2[100001];bool flag;struct spot{ int u,v;}l[100001];void build(int f,int t){ l[++tot]=(spot){f,t}; next[tot]=first[f]; first[f]=tot;}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&ru,&rv); if(jud1[ru]==rv) continue; pas[rv]++; jud1[ru]=rv; build(ru,rv); } for(int i=1;i<=n;i++) if(pas[i]==0) q.push(i); while(!q.empty()) { int x=q.front(); q.pop(); ans[++cnt]=x; for(int i=first[x];i!=-1;i=next[i]) { pas[l[i].v]--; if(pas[l[i].v]==0) q.push(l[i].v); } } if(cnt>=n) printf("o(∩_∩)o"); else { printf("T_T\n"); printf("%d",n-cnt); } return 0;}
阅读全文
1 0
- 最短路,最小生成树,及拓扑排序模板整理
- 最小生成树&最短路模板
- 【模板】最短路&&最小生成树
- 图的遍历(dfs、bfs、最短路、最小生成树、拓扑排序)
- 2017.4.3 机房测试 (并查集,最短路,拓扑排序,最小生成树)
- 「数据结构作业」最短路,拓扑排序,关键路径,最小生成树
- 数据结构实验报告-图算法-最小生成树-最短路-拓扑排序-搜索
- 最短路(最小生成树)
- 拓扑排序+最小生成树
- 20131111:图的应用:最小生成树;拓扑排序;最短路径;最小树形图
- 最小生成树模板整理
- 无向图最小生成树、次小生成树,最短路模板
- 无向图最小生成树、次小生成树,最短路模板
- 无向图最小生成树、次小生成树,最短路模板
- 图的最短路径及最小生成树 模板
- 【区别】最短路&最小生成树
- BOJ 333 最小生成树+最短路
- 区别 最短路跟最小生成树
- java中的多线程深入探究
- hdu 1019 Least Common Multiple 最小公倍数
- Spring中Bean及@Bean的理解
- (crm笔记2-1)struts2层与前端页面的连接
- jsp+Javabean+servlet实现修改
- 最短路,最小生成树,及拓扑排序模板整理
- Search for a Range一打简单的二分题
- odps mapreduce学习笔记
- 快速解读GC日志
- 用Seam实现:图片上传 + 保存到数据库 + 从数据库读出图片并显示到页面中
- 菜谱
- 开关电源设计中电感的选择
- java volatile
- Trapping rain water