【并查集】tree

tree

时间限制:1秒  内存限制: 64 MB

试题描述

    对于完全图G,若有且仅有一棵最小生成树为T,则称完全图G是树T的扩展出的。给你一棵树T,找出T能扩展出的边权和最小的完全图G。

输入要求

     第一行N,(2 <= N <= 10^5)表示树T的点数。 接下来N-1行,Si Ti Di 描述一条边(Si,Ti)权值为 Di。 保证输入数据构成一棵树。

输出要求

     一行一个数,表示最小的图G的边权和。

输入样例

4 1 2 1 1 3 1 1 4 2

输出样例

12

知识点及提示

     添加D(2,3)=2,D(3,4)=3,D(1,4)=3即可。

 题目解析 :首先回顾一下Kruskal算法求最小生成树的方法 -- 将所有的边进行排序,由小到大依次尝试添加进最小生成树中。如果满足这条边的2个端点u和v不连通,那么将这条边加入最小生成树中,否则不能加入。

       借鉴这种方法,将所有的边进行排序,由小到大开始添加进最小生成树。对于当前这条边的2个端点u和v,所处的2个连通块U和V之间必然是还未连通的。加入这条边之后2个才能够连通,换言之,使得这2个连通块连通的权值最小的边就是当前的u和v边。因此被排除的边就是Sum(U)*Sum(V) -1(U中取一个点,V中取一个点,然后排除u,v这条边),而这条边的权值就是w(u,v) + 1。

 

代码如下 :

 

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 #define rep(i, x) for (int i = 1; i <= x; i ++)
 5 
 6 #define WINDOWS
 7 
 8 using namespace std;
 9 
10 #ifdef WINDOWS
11 typedef __int64 int64;
12 #else
13 typedef long long int64;
14 #endif
15 
16 const int Maxn = 1e5 + 1;
17 
18 struct edge
19 {
20     int x, y;
21     int64 c;
22 }A[Maxn];
23 
24 int N, F[Maxn];
25 int64 Sum[Maxn], Ans;
26 
27 void Print()
28 {
29     printf("%I64d", Ans);
30 }
31 
32 void Set_Combine(int x, int y)
33 {
34     F[x] = y;
35     Sum[y] += Sum[x];
36 }
37 
38 int Set_Find(int k)
39 {
40     return F[k] == k ? k : F[k] = Set_Find(F[k]);
41 }
42 
43 void Set_Init()
44 {
45     rep(i, N) { F[i] = i; Sum[i] = 1; }
46 }
47 
48 bool Cmp(edge a, edge b)
49 {
50     return a.c < b.c;
51 }
52 
53 void Solve()
54 {
55     sort(A + 1, A + N, Cmp);
56     Set_Init();
57     rep(i, N - 1)
58     {
59         int x = Set_Find(A[i].x), y = Set_Find(A[i].y);
60         Ans += (Sum[x] * Sum[y] - 1) * (A[i].c + 1);
61         Set_Combine(x, y);
62     }
63 }
64 
65 inline void Scan(int &x)
66 {
67     char c;
68     while (c = getchar(), c < '0' || c > '9'); x = c - '0';
69     while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
70 }
71 
72 inline void Scan(int64 &x)
73 {
74     char c;
75     while (c = getchar(), c < '0' || c > '9'); x = c - '0';
76     while (c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0';
77 }
78 
79 void Init()
80 {
81     Scan(N);
82     rep(i, N - 1)
83     {
84         Scan(A[i].x); Scan(A[i].y); Scan(A[i].c);
85         Ans += A[i].c;
86     }
87 }
88 
89 int main()
90 {
91     Init();
92     Solve();
93     Print();
94     return 0;
95 }

 

 

 

posted on 2012-12-22 13:54  孤星ぁ紫辰  阅读(312)  评论(0)    收藏  举报

导航