思路
这道题的思路很巧妙。
题目给了我们一个图,要我们求最少代价分隔敌人,
我们不妨转化一下,假设这个图没有边,求用最大的代价连边使得每个敌人的城市都分别在一个连通块内。
这样我们可以用并查集连边。
只有两种情况可以连:
- 没有敌人的城市的连通块和有敌人的城市的连通块相连
- 两个没有敌人的城市的连通块相连
最后统计答案即可。
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,k,v[1000010],x,f[1000010],ans;
struct node
{
long long a,b,c;
}e[1000010];
bool cmp(const node&k,const node&g)
{
return k.c>g.c;
}
long long findd(long long fa)
{
if(f[fa]==fa)
return fa;
return f[fa]=findd(f[fa]);
}
int main()
{
cin>>n>>m>>k;
for(long long i=1; i<=k; i++)
{
scanf("%lld",&x);
v[x]=1;
}
for(long long i=0; i<=n-1; i++)
f[i]=i;
for(long long i=1; i<=m; i++)
{
scanf("%lld%lld%lld",&e[i].a,&e[i].b,&e[i].c);
ans+=e[i].c;
}
sort(e+1,e+1+m,cmp);
for(long long i=1; i<=m; i++)
{
long long fa=findd(e[i].a),fb=findd(e[i].b);
if(fa==fb)
ans-=e[i].c;
else if(v[fa]&&!v[fb])
{
f[fb]=f[fa];
ans-=e[i].c;
}
else if(v[fb]&&!v[fa])
{
f[fa]=f[fb];
ans-=e[i].c;
}
else if(!v[fb]&&!v[fa])
{
f[fa]=f[fb];
ans-=e[i].c;
}
}
cout<<ans;
return 0;
}