kuangbin专题八 UVA10462 Is There A Second Way Left?(不错的好题,次小生成树)

题意:
给你N个点,M条边,其中有重边,A,B,C表示A到B的价格为C,连接所有的点,求出最小的价格,如果无法连接所有的点的话就输出No way。如果没有次小生成树的话就输出No second way。如果有的话就输出次小生成树的值。
题解:
次小生成树,做完这道题之后我发现我以前做的都是没有重边的次小生成树,所以一开始我就用prim做这道题,发现难的要死,后来才知道次小生成树的题如果有重边是不能删除的,要保留下来,所以这道题用Kruskal比较好。通过这道题也让我知道了我以前的Kruskal的次小生成树的模板不太行,要重新回去弄一下。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int MAXN=205;
struct node
{
    int u,v,w;
    bool del,used;
}map[MAXN];
int fa[105];
int n,m,cnt;
bool flag;
bool cmp(node c,node d)
{
    return c.w<d.w;
}
void init()
{
    for(int i=1;i<=n;i++)
    fa[i]=i;
}
int find(int p)
{
    return p==fa[p]? p:find(fa[p]);
}
int Kruskal()
{
    int sum=0,num=0;
    init();
    for(int i=0;i<m;i++)
    {
        if(map[i].del)
        continue;
        int P=find(map[i].u);
        int Q=find(map[i].v);
        if(P!=Q)
        {
            sum+=map[i].w;
            fa[P]=Q;
            if(!flag) map[i].used=true;
            num++;
        }
        if(num>=n-1)
        break;
    }
    if(num>=n-1)
    return sum;
    else
    return INF;
}
int main()
{
    int t,k=1;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&map[i].u,&map[i].v,&map[i].w);
            map[i].del=map[i].used=false;
        }
        sort(map,map+m,cmp);
        flag=false;
        int mst=Kruskal();
//      printf("%d\n",mst);
        flag=true;
        int minn=INF;
        for(int i=0;i<m;i++)
        {
            if(map[i].used)
            {
                map[i].del=true;//标记要删除的原最小生成树的边。 
                minn=min(minn,Kruskal());
                map[i].del=false;
            }
        }
        printf("Case #%d : ",k++);
        if(mst==INF)
        printf("No way\n");
        else if(minn==INF)
        printf("No second way\n");
        else
        printf("%d\n",minn);
    }
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值