poj 1679 The Unique MST 【次小生成树+100的小数据量】

题目地址:http://poj.org/problem?id=1679

2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2

Sample Output

3
Not Unique!

次小生成树学习博客:http://blog.csdn.net/niushuai666/article/details/6925258

分析:T组数据,每组n个节点m条边。计算一下,最小生成树是不是独一无二的,如果是就输出最小生成树的权值和,否则输出Not Unique!(不是独一无二的)。
先计算最小生成树,在计算次小生成树,判断两者的值是否相等!输入数据保证不存在重边。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <iostream>
#include <string>
#include <algorithm>
#define N 110
#define INF 0x3f3f3f3f

using namespace std;
int n, m;

int map[N][N];
bool used[N][N];
int pre[N];
bool vis[N];
int dis[N];
int Max[N][N];

int prim()
{
    int ans=0; int i, j;
    memset(vis, false, sizeof(vis));
    memset(used, false, sizeof(used));
    memset(dis, 0, sizeof(dis));
    memset(Max, 0, sizeof(Max));

    pre[1]=-1;
    vis[1]=true;
    for(i=2; i<=n; i++){
        dis[i]=map[1][i];
        pre[i]=1;
    }

    for(int k=0; k<n-1; k++){
        int mm=INF;
        int pos;
        for(i=1; i<=n; i++){
            if(!vis[i]&&mm>dis[i]){
                mm=dis[i];
                pos=i;
            }
        }
        ans+=mm; //在这可以加一条判断 如果找出来的mm==INF 说明不存在最小生成树
        vis[pos]=true;

        used[pos][pre[pos]]=true;
        used[pre[pos]][pos]=true;//pos与pre[pos]之间的边标记使用
        //update
        for(j=1; j<=n; j++){
            if(vis[j])
                Max[j][pos]=Max[pos][j]=max(Max[j][pre[pos]], dis[pos] );
            if(!vis[j]&&dis[j]>map[pos][j])
            {
                dis[j]=map[pos][j];
                pre[j]=pos;
            }
        }
    }
    return ans;
}
int MST;
int sed_mst()//计算次小生成树
{
    int sed=INF;
    int i, j;
    for(i=1; i<=n; i++){
        for(j=i+1; j<=n; j++){
            if(map[i][j]!=INF && !used[i][j])
            {
                sed=min(sed, MST+map[i][j]-Max[i][j]);
            }
        }
    }
    if(sed==INF) return -1;
    return sed;
}

int main()
{
    int tg; scanf("%d", &tg);
    int i, j;
    while(tg--)
    {
        scanf("%d %d", &n, &m);
        for(i=1; i<=n; i++){
            for(j=1; j<=n; j++){
                if(i==j) map[i][j]=0;
                else map[i][j]=INF;
            }
        }//建图的初始化

        int u, v, w;
        for(i=0; i<m; i++){
            scanf("%d %d %d", &u, &v, &w);
            map[u][v]=map[v][u]=w;
        }
        MST=prim();
        //printf("%d\n", MST);

        if(MST==sed_mst()){
            printf("Not Unique!\n");
        }else{
            printf("%d\n", MST);
        }
    }
    return 0;
}

 

kruskal算法实现:

http://www.cnblogs.com/wally/archive/2013/02/03/2890460.html  

(用那个人的代码提交到poj的这道题,耗时比上面的prim号高不少~~~)

 


posted @ 2015-08-20 08:54  我喜欢旅行  阅读(225)  评论(0编辑  收藏  举报