POJ 1679 The Unique MST

求出次小生成树与最小生成树比较,如果相等则不唯一,否则输出最小生成树的权值。

这道题整整花了两个小时的时间,用的是prim算法,用Tlink记录边是否在MST中,然
后枚举不在树中的边,用其权值w[u][v]代替max[u][v]。max[u][v]是MST中连结两

点u,v唯一的路中权值最大的那条边的权值。

/*
Memory: 272K Time: 0MS
Language: C++ Result: Accepted
*/


#include<cstdio>
#include<cstring>
#include<cstdlib>
const int inf = 0x3f3f3f3f;
const int MAXN = 105;
bool Tlink[MAXN][MAXN], vis[MAXN];
int w[MAXN][MAXN], lowc[MAXN], pre[MAXN], max[MAXN][MAXN];
int n, m;

int Max( int a, int b)
{
return a > b ? a : b;
}

int prim()
{
int i, j, p, k;
int minc, res = 0;
memset( vis, false, sizeof vis);
memset( pre, 0, sizeof pre);
memset( max, 0, sizeof max);
vis[1] = 1;
pre[1] = 1;
for( i = 2; i <= n; i ++) { lowc[i] = w[1][i]; pre[i] = 1;}
for( i = 2; i <= n; i ++)
{
minc = inf; p = -1;
for( j = 1; j <= n; j ++) {
if( !vis[j] && lowc[j] < minc){
minc = lowc[j];
p = j;
}
}
vis[p] = true;
res += minc;
max[ pre[p] ][p] = minc;
Tlink[ pre[p] ][p] = true;
Tlink[p][ pre[p] ] = true;
for( k = 1; k <= n; k ++)
max[k][p] = Max( max[ pre[p] ][p], max[k][p]);
for( j = 1; j <= n; j ++)
if( !vis[j] && lowc[j] > w[p][j]) {
lowc[j] = w[p][j];
pre[j] = p;
}
}
return res;
}

int main()
{
int T;
scanf( "%d", &T);
int s, e, t, Ans, ans;
while( T --)
{
scanf( "%d%d", &n, &m);
for( int i = 1; i <= n; i ++)
for( int j = 1; j <= n; j ++)
w[i][j] = inf;
memset( Tlink, false, sizeof Tlink);
for( int i = 1; i <= m; i ++)
{
scanf( "%d%d%d", &s, &e, &t);
w[s][e] = t;
w[e][s] = t;
}
bool ok = true;
Ans = prim();
for( int i = 1; i <= n; i ++)
{
for( int j = 1; j <= n; j ++)
{
if( w[i][j] == inf || Tlink[i][j])
continue;
ans = Ans + w[i][j] - max[i][j];
if( Ans == ans) {
ok = false;
break;
}
}
if( !ok) break;
}
if( ok) printf( "%d\n", Ans);
else printf( "Not Unique!\n");
}
return 0;
}


你可能感兴趣的:(unique)