度度熊的王国战略 (连通图-并查集)

度度熊国王率领着喵哈哈族的勇士,准备进攻哗啦啦族。 

哗啦啦族是一个强悍的民族,里面有充满智慧的谋士,拥有无穷力量的战士。 

所以这一场战争,将会十分艰难。 

为了更好的进攻哗啦啦族,度度熊决定首先应该从内部瓦解哗啦啦族。 

第一步就是应该使得哗啦啦族内部不能同心齐力,需要内部有间隙。 

哗啦啦族一共有n个将领,他们一共有m个强关系,摧毁每一个强关系都需要一定的代价。 

现在度度熊命令你需要摧毁一些强关系,使得内部的将领,不能通过这些强关系,连成一个完整的连通块,以保证战争的顺利进行。 

请问最少应该付出多少的代价。

Input

本题包含若干组测试数据。 

第一行两个整数n,m,表示有n个将领,m个关系。 

接下来m行,每行三个整数u,v,w。表示u将领和v将领之间存在一个强关系,摧毁这个强关系需要代价w 

数据范围: 

2<=n<=3000 

1<=m<=100000 

1<=u,v<=n 

1<=w<=1000 

Output

对于每组测试数据,输出最小需要的代价。

Sample Input

2 1
1 2 1
3 3
1 2 5
1 2 4
2 3 3

Sample Output

1
3

题意:给你一个连通图,你可以去掉一些连通分量,使它变成非连通图,求最小的去掉的连通分量

思路:

      先判断所给的图是否为来连通图,如果不是则输出0,图内一共有N个点,那么根据并查集的性质,会有N-1个点并入到某一个点为根节点的集合中去,所以设Cnt=N-1,每次合并的时候Cnt--;

      Sum[i]数组存储每个点的连通值,即每个点与其他点连接时的权值的和(千万要记住自己与自己连接的权值不要加和

代码:

  

#include<iostream>
#include<cstring>
using namespace std;
const int maxn=3005;
#define inf 0x3f3f3f3f
int pre[maxn];
int sum[maxn];
int n,m;
int find(int x)
{
	if(pre[x]==x)
	   return x;
	return pre[x]=find(pre[x]);
}
bool merge(int x,int y)
{
     int fx=find(x);
     int fy=find(y);
     if(fx!=fy)
     {
     	 pre[fx]=fy;
     	 return true;
	 }
      return false; 
}
int main()
{
    while(~scanf("%d%d",&n,&m))
	{
		int cnt=n-1;
		memset(sum,0,sizeof(sum));
		for(int i=0;i<maxn;i++)
		   pre[i]=i;
		int u,v,w;
		while(m--)
		{
			scanf("%d%d%d",&u,&v,&w);
			if(u==v) continue;//*同一个点的权值不需要加和 
			sum[u]+=w;
			sum[v]+=w;
			if(merge(u,v)) cnt--;//如果没有建立关系,合并,已建立关系, 不需要合并 
		}
		if(cnt!=0) cout<<"0"<<endl;
		else
		{
			int minn=inf;
			for(int i=1;i<=n;i++)
			   if(minn>sum[i])
			      minn=sum[i];
			cout<<minn<<endl; 
		}
	} 	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼爱吃火锅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值