ABC383E题解
ABC383E 题解
题意
给定一张包含
分析
结论
转化为最小生成树的问题,贪心,在 Kruskal 的过程中额外记录一下每个点集中待匹配的
证明1
首先,需要明确为什么“当前边的边权”是路径中的“边权最大值”。
根据 Kruskal 算法的原理,我们先对边权进行了排序,那么我们一定是按照边权大小升序排序来枚举边。
假设在枚举过程中,当前枚举到了一条权值为
在之后对边的枚举中,任何选取都不会对
证明2
然而这条最小生成树中的路径的情况,只是一条路径的边权最大值,那么它为什么是
采用反证法,记我们在最小生成树的流程中选出来的这条边的边权为
证明3
至于为什么要"尽可能多地匹配",这一点从贪心地角度想应该是很明了的,由于
细节
-
- 开 longlong。
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k;
const int N=2e5+10;
struct Edge
{
int u,v,w;
const bool operator <(Edge tmp)const{return w<tmp.w;}
}e[N];
int a[N],b[N];
int fa[N];
int siza[N],sizb[N];
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m>>k;
for(int i=1,u,v,w;i<=m;++i)
{
cin>>u>>v>>w;
e[i]={u,v,w};
}
for(int i=1;i<=k;++i)cin>>a[i],siza[a[i]]++;
for(int i=1;i<=k;++i)cin>>b[i],sizb[b[i]]++;
for(int i=1;i<=n;++i)fa[i]=i;
sort(e+1,e+m+1);
int ans=0;
for(int i=1;i<=m;++i)
{
int fx=find(e[i].u),fy=find(e[i].v);
if(fx==fy)continue;
int w=e[i].w;
int mn=min(siza[fx],sizb[fy]);
ans+=w*mn,siza[fx]-=mn,sizb[fy]-=mn;
mn=min(sizb[fx],siza[fy]);
ans+=w*mn,sizb[fx]-=mn,siza[fy]-=mn;
fa[fx]=fy;
siza[fy]+=siza[fx],sizb[fy]+=sizb[fx];
siza[fx]=0,sizb[fx]=0;
//merge
}
cout<<ans;
return 0;
}