题目描述
1.背景描述Background
P.S.S:“我来自哪里?”WH:“你来自一个图。”P.S.S:“我是谁?”WH:“你是最小生成树。”P.S.S:“我又要到哪里去?”WH:“你要成为一个最小完全图(边权之和最小的完全图)。”P.S.S:“为……为什么啊?”WH:“这是你的宿命!因为你无聊!!!P.S.S!”2.问题描述Description最小生成树P.S.S在宿命的指引下找到了巫师Kismi。P.S.S希望Kismi能帮自己变成一个完全图。Kismi由于某些不可告人的原因,把这件事交给了你。PS: 可以保证,这个最小生成树对于最后求出的完全图是唯一的。7.时间限制Time Limitation每个测试点1s。8.数据规模:Test1-Test10 n<60Test11-Test25 n<20000注释Hint: 对于样例1,我们只需在1-3间加入一条边权为8的边即可得到最小完全图。其权和是4+7+8=19。对于样例2,我们在2-3间加入一条边权为2的边,在2-4和3-4间加入边权为3的边即可得到最小完全图,其权和是:1+1+2+2+3+3=12。感谢吴豪牛对比赛的支持!!!输入格式
输入的第一行是一个整数n,表示生成树的节点数。
接下来有n-1行,每行有三个正整数,依次表示每条边的端点编号和边权。(顶点的边号在1-n之间,边权<maxint)输出格式
一个整数ans,表示以该树为最小生成树的最小完全图的边权之和。
本题乃逆向思维的经典题目啊。
首先O(n^2)的算法肯定是不能过的。
用kruskal算法的逆算法。
经典 经典
1 #include2 #include 3 #define fin cin 4 using namespace std; 5 //ifstream fin("cin.in"); 6 7 long long n,ans=0; 8 long long f[20005],tot[20005]; 9 struct{ long long u,v,w;}edg[20005];10 11 void Quick(long long l,long long r){12 if(l>=r) return ;13 long long i=l,j=r,mid=edg[(l+r)>>1].w;14 while(i<=j)15 {16 while(edg[i].w mid) j--;18 if(i<=j)19 {20 swap(edg[i].u,edg[j].u);21 swap(edg[i].v,edg[j].v);22 swap(edg[i].w,edg[j].w);23 i++;j--;24 } 25 }26 Quick(l,j);27 Quick(i,r);28 }29 30 long long Find(long long v){31 if(f[v]==v) return v;32 f[v]=Find(f[v]);33 return f[v];34 }35 36 int main()37 {38 fin>>n;39 40 for(long long i=1;i >edg[i].u>>edg[i].v>>edg[i].w;42 for(long long i=1;i<=n;++i)43 f[i]=i,tot[i]=1;44 45 Quick(1,n-1);46 47 for(long long i=1;i