【C++心路历程29】严格次小生成树

姊妹题了感觉。另外一种生成树http://blog.csdn.net/ctf109/article/details/74297446

【问题描述】

  小C最近学了很多最小生成树的算法,Prim算法、Kurskal算法、消圈算法等等。

  正当小C洋洋得意之时,小P又来泼小C冷水了。小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是EM,严格次小生成树选择的边集是ES,那么需要满足:(value(e)表示边e的权值)
         
  这下小C蒙了,他找到了你,希望你帮他解决这个问题。

【输入格式】

  第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点x和点y之间有一条边,边的权值为z。

【输出格式】

  包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

【输入样例】

5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6

【输出样例】

11

【数据范围】

数据中无向图无自环;
50% 的数据N≤2 000 M≤3 000;
80% 的数据N≤50 000 M≤100 000;
100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。
【分析】
对于每次枚举的非树边,删除树上(u,v)路径中边权小于它的最大边即可。
其他同上面的传送门。

int Qmax(int u,int v,int ww)
{
    if(dep[u]<dep[v]) swap(u,v);
    int t=-1;
    while(dep[u]!=dep[v]) 
    {
        if(dist[u]-dist[fa[u]]<ww)
            t=max(t,dist[u]-dist[fa[u]]);
        u=fa[u];    
    }
    while(u!=v)
    {
        if(dist[u]-dist[fa[u]]<ww)
            t=max(t,dist[u]-dist[fa[u]]);
        if(dist[v]-dist[fa[v]]<ww)
            t=max(t,dist[v]-dist[fa[v]]);
        u=fa[u],v=fa[v];        
    }
    return t;
}   
void solve()
{
    LL sum=kruskal();
    dfs(1,0,1,0);//给LCA做准备 
    LL ans=inf;
    for(int i=1;i<=m;i++)
    {
        if(used[i]) continue;
        int u=E[i].u,v=E[i].v;
        int t=Qmax(u,v,E[i].c);//计算u->v上的小于E[i].w的最大边权
        LL tt=t;
        if(t<0) continue;
        else ans=min(sum-tt+E[i].c,ans);
    }
    cout<<ans;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值