F - connect the cities HDU - 3371 最小生成树kruskal

补一个:我之前学习并查集时看过一篇博客,说的非常透彻,因为kruskal算法也用到了并查集,所以再提一下
链接:博客
一、介绍下kruskal算法
1.记 Graph 中有v个顶点,e个边
2.新建图 Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边
3.将原图 Graphnew 中所有e个边按权值从小到大排序
4.循环:从权值最小的边开始遍历每条边 直至图 Graphnew 中所有的节点都在同一个连通分量中
如果这条边连接的两个节点于图 Graphnew 中不在同一个连通分量中
添加这条边到图 Graphnew 中
二、图片描述
在这里插入图片描述
在这里插入图片描述
之前看到一个博客总结了一些图论的题:图论题目集合

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
    int s,e,w;
} a[25000+5];
int n,m,k;
int fa[505];
bool cmp(node a,node b)
{
    return a.w<b.w;
}
int Find(int x)
{
    if(fa[x]==x)
        return x;
    return fa[x]=Find(fa[x]);
}
int Kruskal()
{
    sort(a+1,a+m+1,cmp);
    int ans=0;
    for(int i=1; i<=m; i++)
    {
        int x=Find(a[i].s);
        int y=Find(a[i].e);
        if(x!=y)
        {
            ans+=a[i].w;
            fa[x]=y;
        }
    }
    return ans;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>m>>k;
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].w);
        }
        for(int i=1; i<=n; i++)
            fa[i]=i;
        for(int i=1; i<=k; i++)
        {
            int t,x,y;
            scanf("%d%d",&t,&x);
            for(int j=2; j<=t; j++)
            {
                scanf("%d",&y);
                int fx=Find(x);
                int fy=Find(y);
                if(fx!=fy)
                    fa[fx]=fy;
            }
        }
        int ans=Kruskal();
        int sum=0;
        for(int i=1; i<=n; i++)
        {
            if(fa[i]==i)
                sum++;
        }
        if(sum>1)
            cout<<"-1"<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值