次小生成树题目及思路 poj1679

原创 2018年04月16日 13:22:03

下面只是讲讲我对次小生成树一些理解,推荐先去看一下次小生成树的一些概念再来看这篇博客。

首先我们要明确一点,在最小生成树中,任意两个点之间有且仅有一条路径。然后是次小生成树由何而来,必然是最小生成树转变而来。如何转变,应该是将一条不是最小生成树中的边,替换最小生成树的一条边,且替换后任意节点之间还应该有通路。那么思路就来了。由于最小生成树的特点,因此往树中添加一条边,就必然会形成一个环,那么去掉的边也应该是环上属于最小生成树的某一条边。大体思路就是这个样子。

1.先形成最小生成树,同时对于需要标记属于最小生成树的边,下面代码用vis来标记。

2.在每次选取一个离生成树最近的一个点后,需要枚举所有已经加入最小生成树的点,依次更新Max数组,Max[i][j]表示在i节点和j节点的路径上最小生成树的最大权值(因为在最后枚举不是最小生成树的边的时候,显然去掉环上权值最大的边才能使次小生成树的总值尽可能的小)。而Max[i][j]的更新是dp的思想,建议好好理解。

3.最后就是枚举所有不在最小生成树上的边,依次更新次小生成树。

下面的代码是poj1679的题。
就是询问所给出的数据所形成的最小生成树是否为一。
如何判断唯一,只需要判断次小生成树是否和最小生成树相等就行了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int, int>pii;
const int maxn = 105;
int e[maxn][maxn];//图
int vis[maxn][maxn];//标记边
int dis[maxn];//原本是距离数组,但是因为是求最小生成树,因此也可以
int pre[maxn];//前驱节点
int Max[maxn][maxn];//记录最大权值的边
int t, n, m;
int sum;//最小生成树
int minsum;//次小生成树


//bool cmp(pii a,pii b){
//return a.second<b.second;
//}


void prim() {
    priority_queue<pii, vector<pii>, greater<pii> >q;
    //这里求大佬解答,一开始重载了pair的小于号,就是上面所注释掉的语句,但是好像没效果
    dis[1] = 0;
    q.push(pii(0, 1));//距离,节点
    while(!q.empty()) {
        int u = q.top().first;//u是距离
        int v = q.top().second;//v是节点
        q.pop();
        if(dis[v] < u) continue;//如果当前节点是树中节点就返回
        sum += dis[v];
        dis[v] = -1;//一旦已经是树中集合,就记为-1
        if(pre[v] > 0) {
            vis[v][pre[v]] = vis[pre[v]][v] = 1;//pre[i]=j,表示i的前驱节点是j
        }
        for(int i = 1; i <= n; i++) {
            if(i == v) continue; //不知道为什么不可以相等
            if(dis[i] < 0) { //如果已经是树中节点就要更新Max
                Max[i][v] = Max[v][i] = max(Max[pre[v]][i], e[v][pre[v]]);//这里有dp的思想,是核心
            } else if(dis[i] > e[i][v]) {//普通的prim更新操作,多了pre数组的更新
                dis[i] = e[i][v];
                pre[i] = v;
                q.push(pii(dis[i], i));
            }
        }
    }
}
void solve() {
    minsum = inf;
    for(int i = 1; i <= n; i++) {//遍历每一条不在最小生成树的边
        for(int j = 1 + 1; j <= n; j++) { //因为是双向图,所以只要遍历一半图就行了
            if(!vis[i][j]) {//如果不在就更新minsum
                minsum = min(minsum, sum - Max[i][j] + e[i][j]);
            }
        }
    }
    if(minsum == sum) {
        printf("Not Unique!\n");
    } else printf("%d\n", sum);
}
int main() {
    scanf("%d", &t);
    while(t--) {
        sum = 0;
        memset(dis, inf, sizeof(dis));
        memset(vis, 0, sizeof(vis));
        memset(pre, -1, sizeof(pre));
        memset(e, inf, sizeof(e));
        memset(Max, 0, sizeof(Max));
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= m; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            e[u][v] = w;//双向
            e[v][u] = w;
        }
        prim();
        solve();
    }
    return 0;
}

版权声明:希望能在自己成长的道路上帮到更多的人,欢迎各位评论交流 https://blog.csdn.net/yiqzq/article/details/79959373

POJ 1679 浅谈不严格次小生成树

世界真的很大 今天狂刷了好多题,算是图论的一个小小阶段总结吧 其他题实在是有点水,算是复习了一下二分图的性质,但主要目的还是练板子 就由这道题(或是下一道,或者下下)来终结图论的复习吧! 毕竟...
  • BerryKanry
  • BerryKanry
  • 2017-10-10 20:25:20
  • 243

POJ 1679 次小生成树裸题

题意: 给定n个点m条无向带权边的图 问:是否最小生成树唯一 是则输出最小生成树的权值   思路: 求出次小生成树,判断权值是否于最小生成树相同即可。 dp[u][v]  表示在最小生成...
  • qq574857122
  • qq574857122
  • 2014-01-17 21:21:07
  • 1125

次小生成树 poj1679

次小生成树 poj1679 遇到一道需要思考的题,所以把他写下来,见代码注释 #include #include #include//什么是最小生成树?简单说就是第二小的树,这个第二小不一定是总权值第...
  • liyanfeng1996
  • liyanfeng1996
  • 2017-02-04 22:42:53
  • 104

次小生成树(poj1679)

The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20737  ...
  • u012859437
  • u012859437
  • 2014-08-27 15:44:33
  • 359

POJ1679 次小生成树

第一次接触次小生成树。 思路:先生成mst,存储mst的每一条边,然后枚举删除每一条mst中的边,看是否能找出一课次小生成树的权值和最小生成树的权值相等。 如果相等,则不唯一。 So...
  • wuyanyi
  • wuyanyi
  • 2011-08-22 18:29:18
  • 1736

POJ1679次小生成树

判断最小生成树是不是唯一。 #include #include #include const int maxn=110,maxm=10010,INF=100000000; struct node{ ...
  • cnyali
  • cnyali
  • 2015-08-14 22:05:14
  • 650

poj1679次小生成树

次小生成树:是否存在多种情况的最小生成树 把最小生成树连的边保存起来,然后循环,不用其中任意一条边形成最小生成树跟原来答案是否一样 #include #include #include #includ...
  • brightest_star
  • brightest_star
  • 2015-08-05 15:46:33
  • 90

poj1679(次小生成树)

The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 26513 Accept...
  • mymilkbottles
  • mymilkbottles
  • 2016-05-18 01:29:54
  • 281

次小生成树 (POJ1679)

题意:判断一个图的最小生成树是否唯一首先明确一点:最小生成树中任意加一条边必形成环,在该环中任意删除一条边,必定还是生成树,因为生成树的定义是n-1条边且无环。步骤:1、遍历最小生成树的任意两点,连接...
  • bpdwn2017
  • bpdwn2017
  • 2018-03-25 21:45:38
  • 11

POJ 1679 The Unique MST(次小生成树)

POJ 1679 The Unique MST(次小生成树) http://poj.org/problem?id=1679 题意:        给你一个n个节点m条边的无向图,问你该图的最小生成树是...
  • u013480600
  • u013480600
  • 2014-07-19 21:12:03
  • 703
收藏助手
不良信息举报
您举报文章:次小生成树题目及思路 poj1679
举报原因:
原因补充:

(最多只允许输入30个字)