重点内容
1自己的理解:
求次小生成树,与最小生成素,cmpare,不相等才输出权值;反之printf(“Not Unique!\n”);就是要求最小生树独一无二白、、、、、、
就是先求最小生成树T,记录每条边Ei,然后删去Ei之后求最小生成树(每次都只有一条边删去了),与T比较,若=,则printf(“Not Unique!\n”);;若都!=,输出权值
别人的理解:(这里不是我的!!!!!声明哈,,只希望能帮助你理解)
(1)
次二小生成树的应用,先求最小生成树,然后枚举删除的边,再求最小生成树
(2)
http://yomean.blog.163.com/blog/static/189420225201192711331883/
题目大意:给你n个点,然后判断这些点所构成的最小生成树有没有同构异形体。其实就是用次小生成树的思想去判断在MST外有没有一条边可以替换MST里面的一条边,且树的权值不变。
次小生成树的求法要用到DP,不过这是很简单的DP。dp[i][j]表示结点i与结点j所形成的环中的最长的边有多长。dp数组可以在用prim算法求最小生成树的时候得到。当对最小生成树集合中加入一条边(i,j)的时候,就枚举所有的点
状态转移方程:
dp[k][j] = max(dp[k][i],c(i,j));(k != j)
最后,判断有没有一条不在MST上的边map[i][j] = dp[i][j]如果有,则说明最小生成树不唯一。
这里写代码片
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int fa[150],mst,v,m,flag;
struct T
{
int l,r,d;
}N[5000];
//
bool cmp(const T&x,const T&y)
{
return x.d<y.d;
}
//
int Find(int x)
{
return x==fa[x]?x:fa[x]=Find(fa[x]);
}
//
void Set()
{
int i;
for(i=1;i<=v;i++)
fa[i]=i;
}
//
void MST()
{
int i,j,k,ans,cx,fx,fy,cnt,tail[5000];
Set();
cnt=0;
mst=0;
for(i=0;i<m;i++)
{
if(cnt==v-1)
break;
fx=Find(N[i].l);
fy=Find(N[i].r);
if(fx!=fy)
{
fa[fx]=fy;
tail[cnt++]=i;
mst+=N[i].d;
}
}
flag=1;
for(k=0;k<cnt;k++)
{
Set();
cx=0;
ans=0;
for(i=0;i<m;i++)
{
if(i==tail[k])
continue;
fx=Find(N[i].l);
fy=Find(N[i].r);
if(fx!=fy)
{
fa[fx]=fy;
cx++;
ans+=N[i].d;
}
}
if(cx!=cnt)
continue;
if(ans==mst)
{
flag=0;
return ;
}
}
}
//
int main()
{
int t,i;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&v,&m);
for(i=0;i<m;i++)
scanf("%d%d%d",&N[i].l,&N[i].r,&N[i].d);
sort(N,N+m,cmp);
MST();
if(flag==0) //flag==false
printf("Not Unique!\n");
else
printf("%d\n",mst);
}
return 0;
}