Uva 10600 ACM Contest and Blackout(次小生成树)
2016-04-17 15:06
344 查看
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1541
题意:求一个图的最小生成树和次小生成树。
题解:
/*
*算法引入:
*设G=(V,E,w)是连通的无向图,T是图G的一棵最小生成树;
*如果有另一棵树T1,满足不存在树T’,ω(T’)<ω(T1),则称T1是图G的次小生成树;
*
*算法思想:
*邻集的概念:由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);
* /
引用自:/article/8171700.html
代码:
题意:求一个图的最小生成树和次小生成树。
题解:
/*
*算法引入:
*设G=(V,E,w)是连通的无向图,T是图G的一棵最小生成树;
*如果有另一棵树T1,满足不存在树T’,ω(T’)<ω(T1),则称T1是图G的次小生成树;
*
*算法思想:
*邻集的概念:由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);
* /
引用自:/article/8171700.html
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int VMAX=100+5; const int EMAX=VMAX*VMAX; const int INF=0x3f3f3f3f; int g[VMAX][VMAX],maxd[VMAX][VMAX];//g---存图,maxd存树上两点之间路径的最大权 int vis[VMAX]; int dist[VMAX]; int pre[VMAX];//前驱 int use[VMAX][VMAX];//0表示没用过,1表示用过,2表示不存在 int n,m; int firmst,secmst; int prim() { memset(maxd,0,sizeof(maxd)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { dist[i]=g[1][i]; pre[i]=1; } firmst=0; vis[1]=1; for(int i=1;i<n;i++) { int p=-1,mmin=INF; for(int j=1;j<=n;j++) { if(!vis[j]&&mmin>dist[j]) { mmin=dist[j]; p=j; } } if(p!=-1) { use[pre[p]][p]=use[p][pre[p]]=1; for(int j=1;j<=n;j++) { if(vis[j]) { maxd[j][p]=max(maxd[j][pre[p]],g[pre[p]][p]); } } vis[p]=1; firmst+=mmin; for(int j=1;j<=n;j++) { if(!vis[j]&&dist[j]>g[p][j]) { dist[j]=g[p][j]; pre[j]=p; } } } } return firmst; } int secMst() { int mmin=INF; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(use[i][j]==0) mmin=min(mmin,g[i][j]-maxd[i][j]); } } return secmst=firmst+mmin; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { g[i][j]=INF; use[i][j]=2; } } while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); g[a][b]=c; g[b][a]=c; use[a][b]=0; use[b][a]=0; } prim(); secMst(); printf("%d %d\n",firmst,secmst); } return 0; }
相关文章推荐
- 机器学习方法总结
- Android系统版本总结
- EF中映射Oracle存储过程及调用出现的一些问题
- 括号配对问题
- hdu 1129 Diophantus of Alexandria
- AndroidStudio的adb启动问题
- 合并排序实现和分析
- IDL
- Eclipse编译PostgreSQL 9.5.2
- 20145218 《Java程序设计》第7周学习总结
- Struts2再曝高危漏洞(S2-020补丁绕过)
- 有序广播
- GridView分页的实现
- 视频处理器
- Xshell 无法连接虚拟机中的ubuntu的问题
- Android-GridView的图文列表显示
- Html提示框
- C语言中有bool类型吗?
- Android TextView实现跑马灯
- Linux--线程的控制与分离