问题 B: 花园

题目描述
小N经常去小T家的花园里散步,小T家的花园有N个长的⼀样的亭⼦和M条道路连接着亭⼦,但是小T的花园太过于乱了,小N作为⼀个路痴经常进去了之后找不到出来的路,⼀直在环里面绕圈。于是小N要让小T把其中的某些路种上向日葵,使得剩下的路不会出现环。
因为向日葵不⽅便种,⽽第i条路长Li,需要Li个向日葵去种,于是小T想知道他最少要种多少向日葵才能满⾜小N的要求呢?

输入
第⼀⾏两个整数N、M,表示花园的亭⼦数目和道路数目;
接下来M⾏,每⾏3个整数A,B,C,表示有⼀条连接着A和B的长度为C的道路。

输出
输出⼀⾏,⼀个整数,表示小T最少需要种的向日葵数目。

样例输入
复制样例数据
5 5
1 2 5
1 4 4
3 4 3
2 3 2
3 5 1
样例输出
2

提示
对于100%的数据,有N≤100000,M≤200000,0<C≤1000000。

由题意可知图中存在环,我们用kruskal算法,先把边权加起来,同时加入边的时候把他们的边权改为负值。跑一遍kruskal算法求出最小生成树,然后再加上边权的总和即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int f[N];
struct node
{
  int a,b,w;
  bool operator <(const node &W) const
  {
    return w<W.w;
  }
}e[N];
int find(int x)
{
  if(f[x]!=x) f[x]=find(f[x]);
  return f[x];
}
int main()
{
  int n,m;
  ll sum=0;
  scanf("%d %d",&n,&m);
  for(int i=1;i<=m;i++)
  {
    scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].w);
    sum+=e[i].w;
    e[i].w=-e[i].w;
  }
  sort(e+1,e+1+m);
  for(int i=1;i<=n;i++) f[i]=i;
  int cnt=0;
  ll res=0;
  for(int i=1;i<=m;i++)
  {
    int u=e[i].a, v=e[i].b,w=e[i].w;
    int da=find(u),db=find(v);
    if(da!=db)
    {
      f[da]=db;
      res+=w;
      if(++cnt==n-1) break;
    }
  }
  res=res+sum;
  printf("%lld\n",res);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值