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号高不少~~~)