题意:有n个城市,城市之间有n-1条路连接每个城市,也就是说有一个树,敌人在一些城市放了导弹,共有m个导弹,敌人想把导弹运到一起然后开战,现在给你个任务就是摧毁一些路,使任何两个导弹都不能运到一起,摧毁每条路都有相应的代价,求最小的代价。
分析:
导弹不能运到一起就是说任何两个导弹不能在一个连通图中,所以我们的任务就是用最少的代价摧毁一些路使m个导弹分别在m个连通图中。
这题是就反面,最少的代价,那么就是剩下的路的代价越大越好,这就是最大生成树,所以解题方法是:用Kruskal算法求最大生成树,用并查集来维护两个导弹不能在一个连通图中。
代码:
#include<iostream> #include<algorithm> using namespace std; int fa[100005],n,m,t; struct node{ int x,y; long long v; }edge[100005]; int k[100005]; long long sum; bool cmp(node a,node b) { return a.v>b.v; } int find(int x) { if(fa[x]==x) return x; else return fa[x]=find(fa[x]); } void merge(int x,int y) { fa[find(x)]=find(y); } void kruskal() { for(int i=0;i<n-1;i++){ int fax=find(edge[i].x); int fay=find(edge[i].y); if(k[fax]&&k[fay]){ sum+=edge[i].v; continue; } else{ if(k[fax]||k[fay]) k[fax]=k[fay]=1; merge(fax,fay); } } } int main() { cin>>t; while(t--){ memset(k,0,sizeof(k)); cin>>n>>m; for(int i=0;i<n;i++) fa[i]=i; for(int i=0;i<n-1;i++) cin>>edge[i].x>>edge[i].y>>edge[i].v; int tmp; for(int i=0;i<m;i++){ cin>>tmp; k[tmp]=1; } sort(edge,edge+n-1,cmp); sum=0; kruskal(); cout<<sum<<endl; } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-10 08:35:55