2017年浙江工业大学大学生程序设计迎新赛预赛-K:栗酱的连通图(最大生成树)

来源:互联网 发布:十三水配牌算法 编辑:程序博客网 时间:2024/04/30 07:18

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

萌萌哒栗酱有n个点,第i个点有点权ai(ai为偶数),你可以在任意两点之间添加一条边,每一条边的边权为连接它的两个点的点权之和除以2。
现在她需要添加n-1条边,使任意两点相互连通,并且连通后的边权和最大。

输入描述:

第一行一个数T,表示有T组数据。
对于每组数据,第一行输入一个数n,表示点的数量,
接下来一行输入n个数,a1,a2,…,an,其中ai表示第i个点的点权。
任意两个相邻数之间用空格隔开。

输出描述:

对于每一组数据,输出一个数,即最大边权和。
示例1

输入

254 2 4 4 21010 2 6 4 6 8 10 8 2 10

输出

1473

备注:

T≤10
1≤n≤103
1≤ai≤103,保证ai为偶数。
思路:最大生成树。

#include<bits/stdc++.h>using namespace std;struct edg{    int x,y,c;};vector<edg>b;int cmp(const edg& f,const edg& s){return f.c>s.c;}int a[2000],p[2000];int f(int x){return p[x]==x?x:p[x]=f(p[x]);}int main(){    int T;cin>>T;    while(T--)    {        int n;        b.clear();        scanf("%d",&n);        for(int i=1;i<=n;i++)scanf("%d",&a[i]),p[i]=i;        for(int i=1;i<=n;i++)        {            for(int j=i+1;j<=n;j++)b.push_back((edg){i,j,(a[i]+a[j])/2});        }        sort(b.begin(),b.end(),cmp);        int ans=0;        for(int i=0;i<b.size();i++)        {            int fx=f(b[i].x),fy=f(b[i].y);            if(fx==fy)continue;            p[fx]=fy;            ans+=b[i].c;        }        cout<<ans<<endl;    }    return 0;}




阅读全文
1 0
原创粉丝点击