poj 1679 The Unique MST

简介: 点击打开链接poj 1679 思路:最小生成树+次小生成树 分析:判断最小生成树是否是唯一的,那就可以去判断次小生成树是否大于最小生成树。这里就涉及到了次小生成树的求法 求解次小生成树: step 1.

点击打开链接poj 1679


思路:最小生成树+次小生成树
分析:判断最小生成树是否是唯一的,那就可以去判断次小生成树是否大于最小生成树。这里就涉及到了次小生成树的求法
求解次小生成树:
step 1.  先用prim求出最小生成树T.
             在prim的同时,用一个矩阵max[u][v] 记录 在T中连结任意两点u,v的唯一的
             路中权值最大的那条边的权值. (注意这里).
             这是很容易做到的,因为prim是每次增加一个结点s, 而设已经标号了的结点
             集合为W, 则W中所有的结点到s的路中的最大权值的边就是当前加入的这条边.
             step 1 用时 O(V^2).
step 2.  枚举所有不在T中的边uv, 加入边uv则必然替换权为max[u][v]的边。

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define MAXN 1010
#define INF 0XFFFFFFF

int t , n , m;
int vis[MAXN];
int pre[MAXN];/*记录节点的上一个节点*/
int lowcost[MAXN];
int maxvalue[MAXN][MAXN];
int G[MAXN][MAXN];
int mark[MAXN][MAXN];/*标记还有哪些边没被用*/

/*初始化*/
void init(){
    memset(mark , 0 , sizeof(mark));
    memset(maxvalue , 0 , sizeof(maxvalue));
    for(int i = 1 ; i <= n ; i++){
        pre[i] = 1;/*把所有点的上一点都记录为1*/
        for(int j = 1 ; j <= n ; j++)
           G[i][j] = INF;
    }
}

/*prime算法*/
void prime(){
     /*求解最小生成树*/
     memset(vis , 0 , sizeof(vis));
     int ans , pos , min;
     ans = 0;
     vis[1] = 1;
     for(int i = 1 ; i<= n ; i++)
         lowcost[i] = G[1][i];
     for(int i = 1 ; i <= n ; i++){
         pos = -1;
         for(int j = 1 ; j <= n ; j++){
            if(!vis[j] && (pos == -1 || lowcost[j] < lowcost[pos]))
              pos = j;
         }
         vis[pos] = 1;
         ans += lowcost[pos];
         mark[pre[pos]][pos] = mark[pos][pre[pos]] = 0;
         for(int j = 1 ; j <= n ; j++){
             if(vis[j])/*记录maxalue数组*/
                 maxvalue[j][pos] = maxvalue[pos][j] = lowcost[pos];
             if(!vis[j] && lowcost[j] > G[j][pos]){
                 lowcost[j] = G[j][pos];
                 pre[j] = pos;/*记录这些点的上一个节点*/
             }
         }
     }
     /*求解次小生成树*/
     min = INF;
     for(int i = 1 ; i <= n ; i++){
        for(int j = 1 ; j <= n ;j++){
           if(mark[i][j]){
             int tmp = ans-maxvalue[i][j]+G[i][j];
             if(tmp < min)
                 min = tmp;
             mark[i][j] = mark[j][i] = 0;
           }
        } 
     }
     if(ans < min)/*如果不同则说明最小生成树是唯一的*/
         printf("%d\n" , ans);
     else
         printf("Not Unique!\n");
}

int main(){
    int x , y , v;
    scanf("%d" , &t);    
    while(t--){
       scanf("%d%d" , &n , &m);
       init();
       for(int i = 0 ; i < m ; i++){
          scanf("%d%d%d" , &x , &y , &v);
          if(G[x][y] > v){
              G[x][y] = G[y][x] = v;
              mark[x][y] = mark[y][x] = 1;
          }
       }
       prime();
    }
    return 0;
}


目录
相关文章
|
15天前
|
算法 定位技术
The Unique MST(最小生成树的唯一路径)
The Unique MST(最小生成树的唯一路径)
HDU7050.Link with Limit(有向图tarjan找环)
HDU7050.Link with Limit(有向图tarjan找环)
106 0
|
机器学习/深度学习 人工智能 BI
codeforces-1242-B 0-1 MST
B. 0-1 MST time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard output Ujan has a lot of useless stuff in his drawers, a considerable part of which are his math notebooks: it is time to sort them out.
140 0
codeforces-1242-B 0-1 MST
HDU-1598,find the most comfortable road(并查集+枚举)
HDU-1598,find the most comfortable road(并查集+枚举)
|
机器学习/深度学习 存储 人工智能
【POJ 1679 The Unique MST】最小生成树
无向连通图(无重边),判断最小生成树是否唯一,若唯一求边权和。 分析生成树的生成过程,只有一个圈内出现权值相同的边才会出现权值和相等但“异构”的生成树。(并不一定是最小生成树) 分析贪心策略求最小生成树的过程(贪心地选最短的边来扩充已加入生成树的顶点集合U),发现只有当出现“U中两个不同的点到V-U中同一点的距离同时为当前最短边”时,才会出现“异构”的最小生成树。
1211 0