zoukankan      html  css  js  c++  java
  • 次小生成树 克鲁斯卡尔

    题目链接:https://cn.vjudge.net/contest/67265#problem/D

    具体思路:这个题如果用prim的话,对于重边,如果用数组是存不了的,所以可以通过克鲁斯卡尔算法求次小生成树。

    首先,求出最小生成树,在求最小生成树的过程中,记录下都有哪些边被记录到了最小生成树上,然后再试着求次小生成树。

    每一次取最小生成树上的一条边,去除这条边,然后再跑一下克鲁斯卡尔算法,看一下这个时候的总的权值是多少,然后再取一个最小的,如果存在次小生成树的话,这就是次小生成树的值。

    AC代码:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<iomanip>
    #include<cmath>
    #include<stack>
    #include<stdio.h>
    #include<algorithm>
    #include<map>
    using namespace std;
    # define inf 0x3f3f3f3f
    # define maxn 200+100
    # define ll long long
    struct edge
    {
        int fr;
        int to;
        int cost;
    } q[maxn*4];
    int vis[maxn];
    int father[maxn];
    int n,m,ans;
    int num;
    int Find(int t)
    {
        return t==father[t]?t:father[t]=Find(father[t]);
    }
    bool cmp(edge t1,edge t2)
    {
        return t1.cost<t2.cost;
    }
    int krustra1()
    {
        int sum=0;
        for(int i=1; i<=n; i++)
        {
            father[i]=i;
        }
        for(int i=1; i<=m; i++)
        {
            int t1=Find(q[i].fr);
            int t2=Find(q[i].to);
            if(t1!=t2)
            {
                sum+=q[i].cost;
                father[t1]=t2;
                vis[++ans]=i;//记录哪些边在最小生成树上。
            }
        }
        if(ans<n-1)return -1;
        return sum;
    }
    int krustra2(int t)
    {
        int sum=0;
        for(int i=1; i<=n; i++)//记得每一次求的话,重新编号。
        {
            father[i]=i;
        }
        int y=0;
        for(int i=1; i<=m; i++)
        {
            if(t==i)continue;
            int t1=Find(q[i].fr);
            int t2=Find(q[i].to);
            if(t1!=t2)
            {
                sum+=q[i].cost;
                father[t1]=t2;
                y++;
            }
        }
        if(y<n-1)return inf;//如果够不成最小生成树,那么就返回inf
        return sum;
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        int Case=0;
        while(T--)
        {
            ans=0;
            memset(vis,0,sizeof(vis));
            scanf("%d%d",&n,&m);
            for(int i=1; i<=m; i++)
            {
                scanf("%d%d%d",&q[i].fr,&q[i].to,&q[i].cost);
            }
            sort(q+1,q+m+1,cmp);
            int w=krustra1();
            if(w==-1)printf("Case #%d : No way
    ",++Case);
            else
            {
                int temp=inf;
                for(int i=1; i<=ans; i++)
                {
                    temp=min(temp,krustra2(vis[i]));
                }
                if(temp==inf)printf("Case #%d : No second way
    ",++Case);
                else printf("Case #%d : %d
    ",++Case,temp);
            }
        }
        return 0;
    
    }
    
  • 相关阅读:
    Oracle:SQL语句--对表的操作——删除表
    Oracle:SQL语句--对表的操作——修改表名
    Oracle:SQL语句--对表的操作——修改表名
    Oracle:SQL语句--对表的操作—— 删除字段(即删除列)
    网络配置4:vlan间通信配置
    网络配置3:动态路由配置
    网络配置2:静态路由配置
    网络配置0:网络设备基础知识
    网络配置1:VLAN配置
    T-SQL之数据操作(一):增删改
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10262820.html
Copyright © 2011-2022 走看看