题目链接:
题意:
给定一个无向图,一个序列a和一个序列b,b能够重排,求f(ai,bi)的最小值之和
其中f(ai,bi)代表ai节点到bi节点路径中权重最大的一条边的权值
思路:
最小化权值最大边 => kruskal求最小生成树
即每当两个连通块连通时,两个连通块内的节点到另一个连通块的节点的f(i,j)就确定了
利用带权并查集维护每个集合a序列的个数的数量和b序列的个数的数量,具体来说可以开一个cnt数组,如果是a中节点就++,否则--
每次连通都是正的一边和负的一边匹配
int n,m;
struct edge{int u,v,w;bool operator<(const edge&t)const{return w<t.w;}
};
vector<edge>e;
int f[maxn];
int find(int x){if(f[x]!=x)f[x]=find(f[x]);return f[x];
}int cnt[maxn];
void solve(){int k;cin>>n>>m>>k;for(int i=1;i<=n;i++)f[i]=i;for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;e.pb(edge{u,v,w});}vector<int>a(k+1);vector<int>b(k+1);for(int i=1;i<=k;i++){cin>>a[i];cnt[a[i]]++;}for(int i=1;i<=k;i++){cin>>b[i];cnt[b[i]]--;}int ans=0;sort(e.begin(),e.end());for(int i=0;i<e.size();i++){int x=e[i].u,y=e[i].v,w=e[i].w;x=find(x);y=find(y);if(x==y)continue;if(cnt[x]*cnt[y]<0)ans+=min(abs(cnt[x]),abs(cnt[y]))*w;cnt[x]+=cnt[y];f[y]=x; }cout<<ans<<endl;
}