次小生成树 克鲁斯卡尔

题目链接: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\n",++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\n",++Case);
            else printf("Case #%d : %d\n",++Case,temp);
        }
    }
    return 0;

}

 

posted @ 2018-11-14 17:57  Let_Life_Stop  阅读(234)  评论(0编辑  收藏  举报