最小生成树邻接表模板
2014-07-23 18:57
274 查看
/*我的经验是prim加了堆优化之后比kruskal快一点点点点点点。所以99%的时间都是用的kruskal*/ /*prim算法(矩阵形式):*/ #include<stdio.h> #include<algorithm> #define M 6000*3 //双向边 所以要乘 切记 #define inf 0x3f3f3f3f int e;//边数 //prim算法(边表形式): struct Edge//frm为起点,to为终点,w为边权,nxt指向下一个顶点 { int frm; int to,w,nxt; }edge[M]; int vis[M],head[M],dis[M]; void addedge (int cu,int cv,int cw)//生成边的函数 { edge[e].frm = cu; edge[e].to = cv; edge[e].w = cw; edge[e].nxt = head[cu];//前一个.frm=cu的edge编号,如果没有 head[cu]=-1; head[cu] = e ++;//head[cu] 存最后一次存入的edge 编号 edge[e].frm = cv; edge[e].to = cu; edge[e].w = cw; edge[e].nxt = head[cv]; head[cv] = e ++; } int prim(int n,int sta) //n为顶点数量,sta为起点 { if(e/2<n-1) return -1; //边不够 返回-1 表示不完全图 int sum = 0,i,flag; for(i=0;i<n;i++) { dis[i]=inf; } memset(vis,0,sizeof(vis)); for (i = head[sta];i != -1;i = edge[i].nxt)//遍历与sta点相连的所有顶点 { int v = edge[i].to; dis[v] = edge[i].w; } vis[sta] = 1; //加入到最小生成树中 int m = n - 1; //只生成n-1条边,所以循环n-1次 while (m --) { if(n==0) return-1 if(e/2<n-1) return -1; int min = inf; for (i = 0;i < n;i ++)/出当前边权最小的边 { if (!vis[i]&&dis[i] < min) flag = i,min = dis[i]; } if(min==inf) //没找到可以用的边 代表图不完全 返回-1 return -1; sum += dis[flag]; vis[flag] = 1;//加入到最小生成树中 for (i = head[flag];i != -1;i = edge[i].nxt)//更新与flag顶点相连的点的dis { // int v = edge[i].to; if (edge[i].w < dis[v]) dis[v] = edge[i].w; } } return sum; //返回边权总和 } int main () { int a,b,w,n,i,j; while(scanf("%d",&n),n) { memset (head,-1,sizeof(head)); e = 0; //记得初始化 for(i=0;i<n*(n-1)/2;i++) { scanf ("%d%d%d",&a,&b,&w); a--,b--; addedge(a,b,w); } printf("%d\n",prim(n,1)); //prim(int n,int sta) //n为顶点数量,sta为起点 } return 0; } /* 邻接矩阵 int prim(int n,int sta)//n表示有n个顶点,sta表从sta这个顶点出发生成最小生成树 { int mark[M],dis[M],flag; int i,sum = 0,j; //sum是总的最小生成树边权值 for (i = 0;i < n;i ++) //初始化dis[i] 表从顶点sta到点i的权值 { dis[i] = mat[sta][i]; mark[i] = 0; } mark[sta] = 1; //sta 这个顶点加入最小生成树中 for (i = 1;i < n;i ++) //循环n-1次,每次找出一条最小权值的边 n个点的图 { //只有n-1条边 int min = inf; //inf 表无穷大 for (j = 0;j < n;j ++)/出当前未在最小生成树中边权最小的顶点 if (!mark[j] && dis[j] < min) min = dis[j],flag = j; mark[flag] = 1; //把该顶点加入最小生成树中 sum += dis[flag]; //sum加上其边权值 for (j = 0;j < n;j ++) //以falg为起点更新到各点是最小权值 if (dis[j] > mat[flag][j]) dis[j] = mat[flag][j]; } return sum; //返回边权总和 } */
相关文章推荐
- Hihocoder 之 #1097 : 最小生成树一·Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)
- 最小生成树的两个模板
- 模板_krustra最小生成树算法
- HDOJ 题目1233 还是畅通工程(最小生成树,模板)
- 最小生成树-Kruskal算法(模板)
- 最小生成树模板
- POJ 1287 Networking(最小生成树模板)+ HDU 1863 畅通工程
- 最小生成树:POJ1251-Jungle Roads(最小生成树的模板)
- POJ 2485 Highways【最小生成树最大权——简单模板】
- HDU 1233 还是畅通工程 最小生成树 Prim模板的应用
- 洛谷——最小生成树模板
- 最小生成树prim模板
- POJ 1861 Network Krusakl模板题 最小生成树
- 【模板】Kruskal 最小生成树
- 【模板】【最小生成树】【Prim】CODEVS P1078
- Poj 1251 Jungle Roads (邻接表 + 优先队列 + Prime 最小生成树)
- 最小生成树模板【kruskal & prim】
- POJ 1258 Agri-Net 【最小生成树入门题目】【prime模板】
- 【POJ3164】【有向图的最小生成树】【自己的模板】
- Constructing Roads+最小生成树模板题+hdu