博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 1679 The Unique MST(次小生成树)
阅读量:4315 次
发布时间:2019-06-06

本文共 2689 字,大约阅读时间需要 8 分钟。

题意:求解最小生成树的权值是否唯一,即要我们求次小生成树的权值

两种方法求最小生成树,一种用prim算法, 一种用kruskal算法

 

一:用prim算法

对于给定的图,我们可以证明,次小生成树可以由最小生成树变换一边得到。 那么我们可以如下求给定图的次小生成树。首先,我们用prime算法求出图的最小生成树, 在这个过程中记录每条边是否用过,以及两个点之间最短路径上的最大权值F[i,j]

F[i,j]可以如此求得,当加入点u的时候,并且u的父结点是v 那么对于已经在生成树中的节点x F[x,u] = max(F[x,v],w[u][v]),那么我么就可以用Prime算法一样的时间复杂度来求出图的次小生成树。

参考链接:

 

#include 
#include
#include
#include
#include
#include
using namespace std;const int INF=0x3f3f3f3f;int n,m;int ans1,ans2;int w[101][101];int dis[101];int pre[101];int vis[101]; int use[101][101]; //use[i][j]=1表示边(i,j)在最小生成树里,=0则不在int f[101][101]; //f[u][v]表示结点u到结点v的最短路径上边的最大值(即最大边的值)vector
son[101]; //son[i]存储的是与i连接的端点void init() { memset(pre,0,sizeof(pre)); memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(f,0,sizeof(f)); memset(use,0,sizeof(use));}//求最小生成树int solve_MST() { init(); vector
node; int s=1,counts=0,ans=0,tmp,k; dis[s]=0; pre[s]=s; node.push_back(s); //一开始dis都赋值为INF,所以为了减少一点点遍历的时间,node存储的是dis不为INF的点 while(1) { tmp=INF; for(int i=0; i

二:用kruskal算法

枚举删除最小生成树上的边,再求最小生成树,即总共求n-1次最小生成树,取其中最小值。

这道题如果用该方法,有一点要注意,不然的话会一直WA。

我做这道题的时候一直wrong answer的原因是因为, 可能求出的次小生成树正好等于最小生成树的总权值,但是它不连通,即边的个数小于n-1

可以试试这个测试数据:

1

6 7

1 3 1

1 2 2

2 3 3

3 4 0

4 5 4

4 6 5

5 6 6

结果是 12

就是说,如果次小生成树不连通,且最小生成树中被你删的边恰好是权值为0的情况, 这样权值总和仍相等,但不满足生成树的要求。

 

#include 
#include
#include
#include
#include
using namespace std;int t,n,m,cost,x,y,w; //n个节点,m条边int ansMST,secondMST;int numOfEdge;struct Edge{ int u,v; int cost; bool operator < (const Edge& tmp) const { return cost< tmp.cost; }}edge[5500],MSTedge[210];struct UF{ int father[110]; void unit(){ for(int i=1;i<=n;i++){ father[i]=i; } } int find_root(int x){ if(father[x]!=x) father[x]=find_root(father[x]); return father[x]; } void Union(int fa,int fb){ father[fb]=fa; }}uf;//求最小生成树int solveMST(){ int counts=0; int ans=0; //int index=0; for(int i=0;i
=n-1){ break; } if(fu!=fv){ ans+=edge[i].cost; uf.Union(fu,fv); MSTedge[counts].u=u; MSTedge[counts].v=v; MSTedge[counts].cost=edge[i].cost; counts++; } } return ans;}/**a、b表示最小生成树中删去的那条边这里是删去(a,b)边后,求最小生成树*/int solve(int a,int b){ int counts=0; int ans=0; for(int i=0;i
=n-1){ break; } if(fu!=fv){ ans+=edge[i].cost; counts++; uf.Union(fu,fv); } } numOfEdge=counts; return ans;}int main(){ scanf("%d",&t); for(int i=1;i<=t;i++){ scanf("%d%d",&n,&m); for(int j=0;j

 

 

转载于:https://www.cnblogs.com/chenxiwenruo/p/3279771.html

你可能感兴趣的文章
【总结】 NOIp2018考时经历记
查看>>
DIY远程控制开关(tiny6410+LED+yeelink+curl)
查看>>
SGU[130] CIrcle
查看>>
深入V8引擎-Time核心方法之win篇(1)
查看>>
指令操作码与地址码
查看>>
Bogo排序
查看>>
字节对齐
查看>>
基于JavaConfig配置的拦截器使用
查看>>
HTML 个人资料框
查看>>
Selenium+IDEA+Maven+TestNG环境搭建
查看>>
Tyvj1057
查看>>
bzoj2463谁能赢呢?
查看>>
Java复习-arraylist和vector
查看>>
【单镜头反光相机】简介
查看>>
HTTP 之 Content-Type
查看>>
R聚类分析
查看>>
Cognos TM1_10.1.1服务端配置
查看>>
[linux 整理] linux启动过程3
查看>>
centos7下kubernetes(2。kubernetes---start,重要概念)
查看>>
配置对象方法传参
查看>>