说下求次小生出树的思路。 先求得最小生成树。
然后枚举不在生成树上的边E(i),将它加入到最小生成树上,则一定会形成一个环,我们把这个环上的最大边删掉,还是一个生成树。得到其权值W(i) 。min(W(i))即是次小生成树
具体实现时这样更简单:求得最小生成树权值min.
求在最小生成树上,任意两点之间的路径上的最大边,并用二维数组maxed[][]记录下来。 (调用多次spfa()实现)。
枚举所有不在生成树上的边,将其加入到最小生成树,并删除掉该环中在最小生成树上的最大边
则可以得到权值为
ans[i] = min+edge[i].w-maxed[u][v]
取ans的最小值即是次小生成树。
#include "iostream" #include "algorithm" #include "queue" using namespace std; #define MAXSIZE 110 #define INF 999999 int t,m,n; struct node { int u; int v; int w; int flag; }; node edge[MAXSIZE*MAXSIZE]; queue<int>que; int f[MAXSIZE]; int e; int kt;//最小生成树的权值 int vis[MAXSIZE]; int maxed[MAXSIZE][MAXSIZE]; int head[MAXSIZE]; int next[MAXSIZE]; int dis[MAXSIZE]; void addnode(int u,int v,int w,int f) { edge[e].u=u; edge[e].v=v; edge[e].w=w; edge[e].flag=f; next[e]=head[u]; head[u]=e++; } bool cmp(node &a,node &b) { return a.w<b.w; } int findset(int x) { if (x==f[x]) return x; else return f[x]=findset(f[x]); } int kruskal() { sort(edge,edge+e,cmp); int tot=0; int i; for (i=1;i<=n;i++) { f[i]=i; } for (i=0;i<e;i++) { if (findset(edge[i].u)!=findset(edge[i].v)) { //union f[findset(edge[i].v)]=findset(edge[i].u); tot+=edge[i].w; edge[i].flag=1; } } return tot; } void spfa(int s) { while(!que.empty()) { que.pop(); } memset(vis,0,sizeof(vis)); que.push(s); vis[s]=1; int i; for (i=1;i<=n;i++) { dis[i]=INF; } dis[s]=0; while(!que.empty()) { int t=que.front(); que.pop(); for ( i=head[t];i!=-1;i=next[i]) { if (edge[i].flag&&dis[edge[i].v]>dis[t]+edge[i].w) { dis[edge[i].v]=dis[t]+edge[i].w; if (maxed[s][edge[i].v]<edge[i].w) { maxed[edge[i].v][s]=maxed[s][edge[i].v]=edge[i].w; } if (!vis[edge[i].v]) { vis[edge[i].v]=1; que.push(edge[i].v); } } } } } int judge() { int min=INF; //枚举所有不在生成树上的边 for (int i=0;i<e;i++) { if (!edge[i].flag) { //ans = min+edge[i].w-maxed[u][v] int tans=kt+edge[i].w-maxed[edge[i].u][edge[i].v]; if (min>tans) { min=tans; } } } //cout <<min<<endl; return min==kt; } int main() { //freopen("in.txt","r",stdin); scanf("%d",&t); while(t--) { e=0; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); memset(maxed,-1,sizeof(maxed)); while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); addnode(a,b,c,0); } //求得最小生成树的权值 kt=kruskal(); // cout<<"kt: "<<kt<<endl; //bfs 求得点遍历生成树最大的边 for (int i=1;i<=n;i++) { maxed[i][i]=0; spfa(i); } //判断是否具有次小生成树 if (judge()) printf("Not Unique!\n"); else printf("%d\n",kt); } return 0; }
相关推荐
先利用prim算法求出最小生成树,然后通过往MST里加边来判断新生成的最小生成树是否具有最小的权值,POJ上The Unique MST(1679)题是要求判断最小生成树是否唯一,此题其实根本不用这样做,但是为了练习球次小生成树...
普里姆算法是一种贪心算法,它从一个顶点开始,逐步扩展最小生成树,每次添加一条与当前生成树连接且权值最小的边。以下是算法的基本步骤: 1. 初始化:选择图中的任意一个顶点作为初始最小生成树的一部分。 2. 建立...
标题 "POJ 1751 求最小生成树Prim算法(JAVA)" 提到的是一个编程挑战,涉及图论中的经典算法——Prim算法。在计算机科学中,Prim算法是用于寻找加权无向图的最小生成树的一种有效方法。最小生成树是一棵树形结构,...
7. **图算法**:图论是计算机科学中的一大分支,题目可能涵盖DFS、BFS、最小生成树、最短路径等算法。 8. **模拟**:模拟题目要求解题者准确地按照给定的规则执行一系列操作,通常需要细心和耐心。 9. **数据结构...
在图论中,一个连通图的最小生成树是一棵树,它包含图中的所有顶点,并且所有边的权重之和尽可能小。Prim算法是从一个顶点开始,逐步添加边,直到包含所有顶点,每次添加的边都是当前未加入树的边中权重最小的一条。...
2. 每次迭代:在未加入到最小生成树的顶点中,找到与已加入顶点相连的边中权值最小的一条,将这条边的另一端顶点加入到最小生成树中。 3. 重复步骤2,直到所有顶点都加入到最小生成树中,或者没有未加入顶点的边。 ...
同时,对于POJ这类在线判题系统,还需要遵循特定的输入输出格式,确保代码能正确读取输入数据并生成符合规范的输出。 总之,"POJ3122-Pie"是一道结合了算法设计和实际编程技巧的题目,通过解题和阅读解题报告,可以...
4. **最小生成树**:如果涉及网络的基础设施,可能需要找到最小生成树(例如Kruskal's Algorithm或Prim's Algorithm),以最小化破坏成本。 5. **最短路径算法**:Dijkstra's Algorithm或Floyd-Warshall Algorithm...
【描述】题目要求构建一个空间站,具体来说是找到最小生成树,以连接一系列在外太空漂浮的模块。这里运用了Prim算法,这是一种寻找图中最小生成树的经典算法,旨在以最小的总边权和连接所有顶点。计算几何则可能涉及...
最小生成树算法** - **定义**:包括 Prim 算法和 Kruskal 算法。 - **示例题目**: - poj1789 - poj2485 - poj1258 - poj3026 - **应用场景**:适用于构建最小成本网络、电力线路铺设等问题。 **4. 拓扑排序**...
然后,Prim算法每次从尚未加入最小生成树的节点中选择距离起点最近的一个,连接到树中,更新其他节点的距离。重复此过程,直至所有节点都被包含在内。 在提交的代码文件“POJ3026-Borg Maze【BFS+Prim】.cpp”中,...
总的来说,"POJ1035 - Spell checker"不仅是一道编程题目,也是一次对字符串处理、错误检测、算法设计和实现能力的综合检验。参与这样的练习有助于提升编程技能,特别是对于解决实际问题和优化性能的思考。通过阅读...
在图论中,一个无向图的最小生成树是指连接所有顶点的一棵树,其边的权重之和尽可能小。解决这类问题的常见算法有Prim算法和Kruskal算法。 描述中提到的“NULL”表明没有具体的题目描述,但通常POJ题目会提供一个...
6. **图论算法**:包括图的遍历(深度优先搜索和广度优先搜索)、最短路径问题(Dijkstra算法、Floyd-Warshall算法)、最小生成树问题(Prim和Kruskal算法)。 7. **字符串处理**:如KMP算法、Rabin-Karp算法、...
5. **Prim算法和Kruskal算法**:这两种都是解决最小生成树问题的算法,适用于无权图或带权重的图。Prim算法从一个节点开始,每次添加一条最小的边,直到连接所有节点;而Kruskal算法则是按边的权重从小到大排序,...
- **解释**:最小生成树算法主要包括Prim算法和Kruskal算法。 ##### (4) 拓扑排序 - **例题**:poj1094 - **解释**:拓扑排序是对有向无环图的一种排序方式,可以用来解决依赖关系的问题。 ##### (5) 匹配算法 - *...
5. **其他**:位操作、编码解码、模拟、图论问题(最短路径、最小生成树、网络流等)、递归、分治策略等。 每道题目都可能综合运用到多个知识点,而AC代码则代表了解决这些问题的有效方法。通过研究这些代码,我们...
在图论领域,克鲁斯卡尔(Kruskal)算法是一种用于解决最小生成树问题的有效方法。这个问题涉及到在一个加权无向图中找到一棵包括所有顶点的树,其边的权重之和尽可能小。POJ 1679 是一个编程竞赛题目,旨在通过实践...
- **描述**:最小生成树算法包括Prim算法和Kruskal算法。 - **应用场景**:构建连接所有顶点且权重最小的生成树。 - **相关题目**: - POJ 1789 - POJ 2485 - POJ 1258 - POJ 3026 #### 3. 流网络算法 - **描述...
标题中的“POJ 1789 最小生成树之prim算法”指的是一个在线编程竞赛题目,来源于普林斯顿开放在线课程(POJ)平台。该题目要求参赛者实现Prim算法,这是一种解决图论问题中寻找最小生成树的经典算法。最小生成树是在...