无向图最小生成树、次小生成树,最短路模板
来源:互联网 发布:套利交易软件 编辑:程序博客网 时间:2024/05/13 04:50
最小生成树有两种模板,都比较简单。
prime算法:
#include<stdio.h>#include<string.h>#define MAX 99999999int g[110][110];int n;int prim(){ int low[110]; int flag[110]; memset(flag,0,sizeof(flag)); for(int i=1; i<=n; i++) { low[i]=g[1][i]; } int count=0; flag[1]=1; for(int i=1; i<n; i++) { int min=MAX+1; int k; for(int j=1; j<=n; j++) { if(flag[j]==0&&min>low[j]) { min=low[j]; k=j; } } flag[k]=1; count+=low[k]; for(int j=1; j<=n; j++) { if(flag[j]==0&&low[j]>g[j][k]) { low[j]=g[j][k]; } } } return count;}int main(){ while(scanf("%d",&n)!=EOF) { int sum; sum=prim(); printf("%d\n",sum); } return 0;}
kruskal算法:
#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#define MAX 6005using namespace std;typedef struct{ int v1,v2,distance;} Edge;Edge roads[MAX+1];int tree[110];bool cmp(const Edge&a,const Edge&b){ return a.distance<b.distance;}int Find(int x){ while(x!=tree[x]) x=tree[x]; int u=x,v; while(tree[u]!=x) { v=tree[u]; tree[u]=x; u=v; } return x;}void Union(int x,int y){ int fx=Find(x),fy=Find(y); if(fx!=fy) tree[fx]=fy;}int main(){ int n,q,a,b,i,j,k,tmp,sum; while((scanf("%d",&n))!=EOF) { for(i=0; i<110; ++i) { tree[i]=i; } sort(roads,roads+k,cmp); for(i=0,sum=0; i<k; ++i) { if(Find(roads[i].v1)!=Find(roads[i].v2)) { Union(roads[i].v1,roads[i].v2); sum+=roads[i].distance; } } printf("%d\n",sum); } return 0;}
以下是次小生成树思想:
邻集的概念:由T进行一次可行交换得到的新的生成树所组成的集合,称为树T的邻集,记为N(T);
设T是图G的最小生成树,如果T1满足ω(T1)=min{ω(T’)|T’∈N(T)},则T1是G的次小生成树;
首先先求该图的最小生成树T,时间复杂度O(Vlog2V+E);
然后,求T的邻集中权值和最小的生成树,即图G 的次小生成树;
如果只是简单的枚举,复杂度很高;
首先枚举两条边的复杂度是O(VE),再判断该交换是否可行的复杂度是O(V),则总的时间复杂度是O(V2E);
分析可知,每加入一条不在树上的边,总能形成一个环,只有删去环上的一条边,才能保证交换后仍然是生成树;
而删去边的权值越大,新得到的生成树的权值和越小,可以以此将复杂度降为O(VE);
更好的方法:首先做一步预处理,求出树上每两个结点之间的路径上的权值最大的边;
然后枚举图中不在树上的边,有了预处理,就可以用O(1)的时间得到形成的环上的权值最大的边;
预处理:因为是一棵树,只要简单的BFS即可,预处理所要的时间复杂度为O(V2);
#include<stdio.h>#include<string.h>#include<algorithm>#define M 107#define inf 0x3f3f3fusing namespace std;int g[M][M],path[M][M];//path求的是i到j最大的边权int dist[M],pre[M],vis[M];bool used[M][M];//是否在最小生成树中int n,m,mst;void init(){ for(int i=0;i<=n;i++) for(int j=i+1;j<=n;j++) g[i][j]=g[j][i]=inf;}int prime(){ int mst=0; memset(path,0,sizeof(path)); memset(vis,0,sizeof(vis)); memset(used,0,sizeof(used)); vis[1]=1; for(int i=1;i<=n;i++) { dist[i]=g[1][i]; pre[i]=1; } for(int i=1;i<n;i++) { int u=-1; for(int j=1;j<=n;j++) { if(!vis[j]) if(u==-1||dist[j]<dist[u]) u=j; } used[u][pre[u]]=used[pre[u]][u]=true;//加入mst mst+=g[pre[u]][u]; vis[u]=1; for(int j=1;j<=n;j++) { if(vis[j]&&j!=u)//从u到j这条路径上最大边的权值 path[j][u]=path[u][j]=max(path[j][pre[u]],dist[u]); if(!vis[j]) if(dist[j]>g[u][j])//更新相邻节点的距离 { dist[j]=g[u][j]; pre[j]=u;//记录他的前驱 } } } return mst;}int second_tree()//求次小生成树{ int res=inf; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j&&!used[i][j]) res=min(res,mst-path[i][j]+g[i][j]);//删除树上权值最大的路径并且加上这条路径其它边 return res;}int main(){ int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); init(); mst=prime();//最小生成树 int second_mst=second_tree();//次小生成树 }}
最短路也有两种简单的算法。
Dijkstra算法:
#include<iostream>#include<stdio.h>#include<iomanip>using namespace std;#define N 10000#define MAX 100000099int a[N][N];int dist[N];void dijkstra(int n){ int s[N],newdist; for(int i=1; i<=n; i++) { dist[i]=a[1][i]; s[i]=0; } dist[1]=0; s[1]=1; for(int i=2; i<=n; i++) { int j,tem=MAX; int u=1; for(j=2; j<=n; j++) if(!s[j]&&dist[j]<tem) { u=j; tem=dist[j]; } s[u]=1; for(j=2; j<=n; j++) { if(!s[j]&&a[u][j]<MAX) { newdist=dist[u]+a[u][j]; if(newdist<dist[j]) dist[j]=newdist; } } }}int main(){ int n,m; while(scanf("%d%d",&n,&m),m||n) { for( i=1; i<=n; i++) { for(j=1; j<=n; j++) a[i][j]=MAX; dist[i]=MAX; } dijkstra(n); cout<<dist[n]<<endl; } return 0;}
Floyd算法:
#include<stdio.h>int map[105][105];int main(){ int n,m,i,j,k,a,b,c; while(scanf("%d%d",&n,&m),n|m) { for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=10000000; for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(map[i][k]+map[k][j]<map[i][j]) map[i][j]=map[i][k]+map[k][j]; printf("%d\n",map[1][n]); } return 0;}
0 0
- 无向图最小生成树、次小生成树,最短路模板
- 无向图最小生成树、次小生成树,最短路模板
- 无向图最小生成树、次小生成树,最短路模板
- 无向图最小生成树、次小生成树、最短路径模版
- 最小生成树&最短路模板
- 【模板】最短路&&最小生成树
- 最短路(最小生成树)
- 1212 . 无向图最小生成树
- 1212 无向图最小生成树
- 无向图最小生成树
- 无向图最小生成树
- 无向图最小生成树
- 无向图最小生成树
- 1212 无向图最小生成树
- 次小。最小生成树
- 最短路,最小生成树,及拓扑排序模板整理
- 最小生成树-->次小生成树
- 最小生成树&&次小生成树
- 《PHP和MySQL Web开发》学习笔记:4~5章
- JavaScript截取字符串方法详解
- ArcGIS Runtime SDK for iOS开发系列教程(4)——如何让你的iOS应用具有GIS能力
- CodeCombat-辱骂
- Linux内核设计的艺术-文件操作
- 无向图最小生成树、次小生成树,最短路模板
- Flash之top boot和bottom boot(转载)
- 终于小松一口气,上来冒个泡
- poj 3617
- 企业自助建站的优势
- SiteMesh
- 学校1027: 大数乘法
- LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
- 账号被封求解锁