原题连接: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);
}
}