给定一棵n个点的图上的最小生成树,让你把它补成完全图,使得新图的MST还是给定的MST且边权和最小,输出需要增加的边权和。
设size[i]表示以i号为祖先的并查集的大小。
首先按边权排序,之后在做MST的过程中,答案cnt+=(size[v]*size[u]-1)*(w+1),来解释一下这个式子,从v号集合到u号集合每两个点之间连一条边(除了MST上的这条边),因为MST必须还是原来的MST,所以边权要加1,之后将集合合并直到求出MST为止即可。
下面给出参考代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #define N 6005 5 using namespace std; 6 int read() 7 { 8 int x=0,f=1;char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} 11 return x*f; 12 } 13 int t,n,m,x,y,z,cnt,parent[N],size[N]; 14 struct node 15 { 16 int u,v,w; 17 }f[N]; 18 bool cmp(node a,node b) 19 { 20 return a.w<b.w; 21 } 22 int find(int x) 23 { 24 if(parent[x]==x)return x; 25 return parent[x]=find(parent[x]); 26 } 27 int main() 28 { 29 t=read(); 30 while(t--) 31 { 32 cnt=0; 33 n=read(); 34 for(int i=1;i<n;i++) 35 { 36 x=read();y=read();z=read(); 37 f[i].u=x;f[i].v=y;f[i].w=z; 38 } 39 for(int i=1;i<=n;i++)parent[i]=i,size[i]=1; 40 sort(f+1,f+n,cmp); 41 for(int i=1;i<n;i++) 42 { 43 int u=find(f[i].u),v=find(f[i].v); 44 parent[u]=v; 45 cnt+=(size[u]*size[v]-1)*(f[i].w+1); 46 size[v]+=size[u]; 47 } 48 cout<<cnt<<endl; 49 } 50 return 0; 51 }