Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 4816 | Accepted: 1598 |
Description
Definition 1 (Spanning Tree): Consider a connected, undirected graph G = (V, E). A spanning tree of G is a subgraph of G, say T = (V', E'), with the following properties:
1. V' = V.
2. T is connected and acyclic.
Definition 2 (Minimum Spanning Tree): Consider an edge-weighted, connected, undirected graph G = (V, E). The minimum spanning tree T = (V, E') of G is the spanning tree that has the smallest total cost. The total cost of T means the sum of the weights on all the edges in E'.
Input
Output
Sample Input
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!
题目要求:求出最小生成树,再求出次小生成树,如果次小生成树与最小生成树的大小相同,则输出Not Unique!
否则输出最小生成树的大小!
通用的次小生成树有两种解法!
1:用求最小生成树的方法,求出最小生成树,并记录下该最小生成树上的所有边!
对该生成树上的所有边都进行枚举。对边集中,除了生成树上某条边的集合,构造最小生成树,并记录下最小值!
当生成树上的边枚举完,得到的值的大小就是次小生成树的大小!
2:首先求出原图最小生成树,权值之和为min
枚举添加每条不在最小生成树上的边 ,加上以后一定会形成一个环。
找到环上除了(u,v)以外的权值最大的边,把它删掉,计算当前生成树的权值之和。
枚举完所有边之后,得到的最小值即为次小生成树的权值。
具体实现时,更简单的方法是从每个节点i遍历整个最小生成树
定义F[i][j]为在生成树上,从i到j的路径上最大的边的权值。通过BFS,求出F[i][j]的值
然后对于添加每条不在最小生成树中的边(i,j),并删去该环中的原生成树的的最大边。
新的生成树权值之和就是Min + w(i,j) – F[i][j]
记录其最小值,则为次小生成树。
伪代码如下:
第一种解法转自队友yzy123
hi.baidu.com/yzy杨子衍/blog/item/0acd5809cb9129db63d98643.html
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct
{
int w;
int x;
int y;
}a[10000];
int r[105],ms,sms;
int used[105]; //记录最小生成树的每一条边
int cmp(const void *a,const void *b)
{
return *(int *)a-*(int *)b;
}
int find(int x)
{
int t=x;
while (r[x]!=x)
x=r[x];
r[t]=x;
return x;
}
int bing (int x,int y)
{
x=find(x);
y=find(y);
if (x==y) return 0;
r[x]=y;
return 1;
}
int main ()
{
int i,j,t,n,m,p,flog;
scanf("%d",&t);
while (t--)
{
scanf("%d %d",&n,&m);
for (i=0;i<105;i++)
r[i]=i;
for (i=0;i<m;i++)
scanf("%d %d %d",&a[i].x,&a[i].y,&a[i].w);
qsort(a,m,sizeof(a[0]),cmp);
ms=0;p=1;i=0; //建最小生成树
while (p<n && i<m)
{
if (bing (a[i].x,a[i].y))
{
ms+=a[i].w;
used[p]=i;
p++;
}
i++;
}
flog=0;
for (j=1;j<n;j++) //每删掉原来最小生成树的一条边,就重建一棵树
{
for (i=0;i<105;i++)
r[i]=i;
sms=0;p=n-1;i=0;
while (p && i<m)
{
if (i!=used[j] &&bing (a[i].x,a[i].y))
{
sms+=a[i].w;
p--;
}
i++;
}
if (sms==ms && !p) {flog=1;break;}
}
if (flog) printf ("Not Unique!/n");
else printf ("%d/n",ms);
}
return 0;
}
第二种解法(由于使用了stl,致使该解法效率变低)