自学内容网 自学内容网

最小生成树 多点连边(2024CCPC 山东省赛 J)

//这题型似乎从前在图论里面做过类似的。也是很多点,求最小生成树,则先生成一颗,其它点连最小边即可。

看一下题目:


原题链接:

Problem - J - Codeforces

J. Colorful Spanning Tree

time limit per test

2 seconds

memory limit per test

1024 megabytes

BaoBao has many colored vertices. The colors are numbered from 11 to nn (both inclusive), and there are aiai vertices of color ii. As BaoBao has just learnt the minimum spanning tree problem in his algorithm class, he decides to practice it with the vertices.

Each pair of vertices is connected by an weighted edge. The weight of each edge is only related to the colors of its two endpoints. More precisely, let cucu be the color of vertex uu, if an edge connects vertices uu and vv, its weight will be bcu,cvbcu,cv.

Help BaoBao calculate the total weight of the minimum spanning tree of the graph.

Recall that a minimum spanning tree is a subset of the edges in a connected, weighted graph that connects all the vertices without any cycles and with the minimum possible total weight.

Input

There are multiple test cases. The first line of the input contains an integer TT indicating the number of test cases. For each test case:

The first line contains an integer nn (1≤n≤1031≤n≤103) indicating the number of different colors.

The second line contains nn integers a1,a2,⋯,ana1,a2,⋯,an (1≤ai≤1061≤ai≤106), where aiai is the number of vertices with color ii.

For the following nn lines, the ii-th line contains nn integers bi,1,bi,2,⋯,bi,nbi,1,bi,2,⋯,bi,n (1≤bi,j≤1061≤bi,j≤106) where bi,jbi,j is the weight of an edge connecting two vertices with color ii and jj. It's guaranteed that bi,j=bj,ibi,j=bj,i for all 1≤i,j≤n1≤i,j≤n.

It's guaranteed that the sum of nn over all the test cases doesn't exceed 103103.

Output

For each test case, output one line containing one integer, indicating the total weight of the minimum spanning tree.


这题其实挺裸的哦,都告诉你是最小生成树了,其实只要多写点题目就能会的。但当时考的时候就一直在想这么多边怎么连,一点没想到正解。。。

正解:有很多点,且每两个点之间就可以有一条边,这是题目大前提。那么这种题肯定不能每条边都加。我们寻思,每个点其实都有一个最小出边(到另一个序号的点)。所以在连通的情况下,这个点只要连最小出边就好啦(连到树上就好)。所以我们的做法就是假设每个颜色的点只有一个,把这些点求个最小生成树,每个颜色的其它点连最小出边即可。

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define int long long 
 
int t;
int n;
struct EDGE{
int u,v,l;
}edge[1000010];
int a[1000010],fa[1000010],minl[1000010];
 
void init(int n){
for(int i=1;i<=n;i++){
fa[i]=i;
}
}
 
int find(int i){
if(fa[i]==i){
return fa[i];
}
fa[i]=find(fa[i]);
return fa[i];
}
 
bool sorrt(struct EDGE i,struct EDGE j){
return i.l<j.l;
}
 
void solve(int n){
memset(minl,0x3f,sizeof minl);
for(int i=1;i<=n;i++){
cin >> a[i];
}
init(n);
int tot=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
edge[tot].u=i;
edge[tot].v=j;
cin>>edge[tot].l;
minl[i]=min(minl[i],edge[tot].l);
tot++;
}
}
sort(edge,edge+tot,sorrt);
int ans=0;
for(int i=0;i<tot;i++){
int fa_u=find(edge[i].u),fa_v=find(edge[i].v);
if(fa_u!=fa_v){
fa[fa_u]=fa_v;
ans+=edge[i].l;
}
}
for(int i=1;i<=n;i++){
a[i]--;
if(a[i]){
ans+=a[i]*minl[i];
}
}
cout<<ans<<endl;
}
 
 
signed main()
{
cin>>t;
while(t--){
cin>>n;
solve(n);
}
return 0;
}

这题真的挺裸了啊,还是做不起来。。。下次要打嘴。


原文地址:https://blog.csdn.net/2301_81888203/article/details/142720512

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!