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