The Unique MST

重点内容
这里写图片描述

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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值