时间限制: 1 Sec  内存限制: 128 MB

题目描述

小粉兔用集训队的奖金买下了一片地。

这片地上有 n 个房子,有些房子之间有道路,有些房子之间则是杂草。

她可以花费一定的代价拆毁一条道路,或是啃光一片草使得两个房子间可以通行(大雾)。

她喜欢生成树,所以她要让所有道路形成一棵生成树。

求最小花费。

输入

第一行一个数,n。

接下来 n 行,每行 n 个数,代表 ai,j。如果为正数,说明它们之间没有道路,需要 ai,j的花费来修建;如果为负数,说明它们之间有道路,需要 −ai,j的花费来拆毁。

输出

一行一个数,代表最小花费。

样例输入

3
0 1 -3
1 0 5
-3 5 0

样例输出

1

提示

对于 100% 的数据,5≤n≤1000,1≤|ai,j(i≠j)|≤1000,保证所有 ai,i=0且 ai,j=aj,i 。

题解

  一道最小生成树。拆边和建边分开算。建边:从小到大建边。拆边:从小到大拆,这条边如果加到最小生成树上,不需要花费任何费用,不在最小生成树上就要花费-aij拆掉。不是很难想,可能比较麻烦。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N = 1009;
 6 struct Edge
 7 {
 8     int x, y, z;
 9     bool operator < (const Edge&a)
10     const
11     {
12         return z < a.z;
13     }
14 }g[N*N], p[N*N];
15 int n, m1, m2, ans, f[N], sum;
16 int find(int x)
17 {
18     if(x != f[x])
19         f[x] = find(f[x]);
20     return f[x];
21 }
22 int main()
23 {
24     scanf("%d", &n);
25     for(int i = 1; i <= n; i++)
26         for(int j = 1; j <= n; j++)
27         {
28             int d;
29             scanf("%d", &d);
30             if(j <= i) continue;
31             if(d > 0)
32             {
33                 ++m1;
34                 g[m1].x = i;
35                 g[m1].y = j;
36                 g[m1].z = d;
37             }
38             else
39             {
40                 ++m2;
41                 p[m2].x = i;
42                 p[m2].y = j;
43                 p[m2].z = d;
44             }
45         }
46     for(int i = 1; i <= n ;i++) f[i] = i;
47     sort(g+1, g+m1+1);
48     sort(p+1, p+m2+1);
49     for(int i = 1; i <= m2; i++)
50     {
51         int fx = find(p[i].x);
52         int fy = find(p[i].y);
53         if(f[fx] != f[fy])
54             f[fy] = f[fx];
55         else
56             ans -= p[i].z;
57     }
58     for(int i = 1; i <= m1; i++)
59     {
60         int fx = find(g[i].x);
61         int fy = find(g[i].y);
62         if(f[fx] != f[fy])
63         {
64             ans += g[i].z;
65             f[fy] = f[fx];
66         }
67     }
68     printf("%d\n", ans);
69     return 0;
70 }
View Code

 

posted @ 2020-05-20 21:38  Johnny-English  阅读(235)  评论(0编辑  收藏  举报