HDU OJ 4313 Matrix【克鲁斯卡尔算法变形】

原题连接:http://acm.hdu.edu.cn/showproblem.php?pid=4313

题意: 毁坏链接有Machines城市之间的路,使得所有有 Machines 的城市不能相互链接!!给出 n 个城市,n - 1条路,m个有 Machines的城市,给出每条路的城市  x,y,以及毁坏这条路的时间 z 。求的怎样毁坏路 能在最短的时间  达到目的!,输出最短时间。

思路:把所有的城市都看作是无路的即孤立的的点,然后 依次判断是否加上每条路(之前对每条路按照时间大小排序,大——小),若该路加上不影响 最终目的,即加上sum += z(该路时间)。遍历完所有的路后 将所有路的总时间max - sum 即使答案!!加上路的过程就是 一个类似克鲁斯卡尔的算法,在用并查集 处理时 注意:让有  Machines 的 城市当 根节点!!这样利于判断是否加路。具体看代码。

还有:注意数据范围!!!int 存不下?!!max和 sum 要用 __int64

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int ac[110000],father[110000];
__int64 sum;
struct hello
{
	int x,y,z;
}yi[110000];
bool cmp(hello t1,hello t2)
{
	return t1.z>t2.z;
}
int find(int x)
{
	if(x!=father[x])
		father[x]=find(father[x]);
	return father[x];
}
void add(int x,int y,int z)
{
	x=find(x);
	y=find(y);
	if(ac[x]&&ac[y])
		return ;
	else
	{
		if(ac[x])
		{
			father[y]=x;
		}
		else
			father[x]=y;
		sum+=z;
	}
}
int main()
{
	int a,b,n,m,ncase,i;
	scanf("%d",&ncase);
	while(ncase--)
	{
		__int64 max=0;
		sum=0;
		scanf("%d%d",&n,&m);
		memset(ac,0,sizeof(ac));
		for(a=0;a<=n;a++)
			father[a]=a;
		for(a=0;a<n-1;a++)
		{
			scanf("%d%d%d",&yi[a].x,&yi[a].y,&yi[a].z);
			max+= yi[a].z;
		}
		for(a=0;a<m;a++)
		{
				scanf("%d",&b);
				ac[b]=1;
		}
		sort(yi,yi+n-1,cmp);
		for(a=0;a<n-1;a++)
			add(yi[a].x,yi[a].y,yi[a].z);
		printf("%I64d\n",max-sum);
	}
}


你可能感兴趣的:(算法,Matrix)