• poj1861&&zoj1542 Network ——最小生成树入门题_Kruscal算法


    题目链接:http://poj.org/problem?id=1861 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=542

    题目大意:

      给n个点,m条边。求一棵生成树,并且满足任意两点之间的距离的最大值最小。输出这个最大值,然后输出树的边的数量,最后输出树的每条边。

    题目思路:

      其实就是求最小生成树。关键就是证明,对于一个图的最小生成树来说,它的最大边满足在所有的生成树的最大边里最小。这是可以理解的。简单思考一下:假设最小生成树不满足这个条件。那么就是说,存在另一棵生成树,它的最大边的值比最小生成树还小,但是它的权值之和可能比最小生成树大,但是这表明,构造最小生成树的时候,存在一步,选择边的时候,没有选择权值最小的,这是不可能的。所以矛盾。所以假设不成立。所以,问题就转化成了常规的求最小生成树的问题了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cctype>
     6 #include <stack>
     7 #include <queue>
     8 #include <map>
     9 #include <set>
    10 #include <vector>
    11 #include <cmath>
    12 #include <algorithm>
    13 #define lson l, m, rt<<1
    14 #define rson m+1, r, rt<<1|1
    15 using namespace std;
    16 typedef long long int LL;
    17 const int MAXN =  0x3f3f3f3f;
    18 const int  MIN =  -0x3f3f3f3f;
    19 const double eps = 1e-9;
    20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
    21   {1,1},{1,-1},{-1,-1}};
    22 const int MAX = 1000+10;
    23 const int MAX1 = 15000+10;
    24 typedef struct Edge {
    25   int u, v, w;
    26   bool operator < (const Edge &other) const {
    27     return w < other.w;
    28   }
    29 };
    30 struct re {
    31   int u, v;
    32 }Re[MAX];
    33 Edge edge[MAX1];
    34 int parent[MAX];
    35 int n, m, sum;
    36 void init()
    37 {
    38   for (int i = 1; i <= n; ++i) parent[i] = -1;
    39 }
    40 int Find(int x)
    41 {
    42   int s;
    43   for (s = x; parent[s] >= 0; s = parent[s]) ;
    44   while (s != x) {
    45     int tmp = parent[x]; parent[x] = s; x = tmp;
    46   }
    47   return s;
    48 }
    49 void Union(int R1, int R2)
    50 {
    51   int r1 = Find(R1), r2 = Find(R2), tmp = parent[r1] + parent[r2];
    52   if (parent[r1] > parent[r2]) {
    53     parent[r1] = r2; parent[r2] = tmp;
    54   } else {
    55     parent[r2] = r1; parent[r1] = tmp;
    56   }
    57 }
    58 void kruscal()
    59 {
    60   init();
    61   int i, j = 0, u, v, w, cnt = 0, Max = 0;
    62   for (i = 0; i < m; ++i) {
    63       u = edge[i].u; v = edge[i].v; w = edge[i].w;
    64     if (Find(u) != Find(v)) {
    65       sum += w; Union(u, v); cnt++;
    66       if (w > Max) Max = w;
    67       Re[j].u = u; Re[j].v = v; j++;
    68     }
    69     if (cnt >= n - 1) break;
    70   }
    71   cout << Max << endl << n - 1 << endl;
    72   for (i = 0; i < j; ++i) {
    73     printf("%d %d\n", Re[i].u, Re[i].v);
    74   }
    75 }
    76 int main(void){
    77 #ifndef ONLINE_JUDGE
    78   freopen("poj1861.in", "r", stdin);
    79 #endif
    80   int i, j;
    81   while (~scanf("%d%d", &n, &m)) {
    82     sum = 0; int u, v, w;
    83     for (i = 0; i < m; ++i) {
    84       scanf("%d%d%d", &u, &v, &w);
    85       edge[i].u = u; edge[i].v = v; edge[i].w = w;
    86     }
    87     sort(edge, edge + m);
    88     kruscal();
    89   }
    90 
    91   return 0;
    92 }

    这题应该属于简单题,但是还是卡了一下。原因很悲催,输入里面的格式控制符多打了一个“%”,我去……结果怎么也出不来啊,直接输出输入的数字也数不出来!竟然很长时间都没有发现,后来还是把输入的部分重新打了一遍,才发现问题。唉,最近老是打错……

    还有就是,题目里面的样例输出是错的……好吧,,第一次遇到这种情况。。还好看的是书里面的翻译和解释,要不又得把题目一遍一遍地读……

  • 相关阅读:
    5.3 java虚拟机的体系结构
    5.2 java虚拟机的生命周期
    3.11.5 doPrivileged()方法
    3.11.1 implies方法
    MT【178】平移不变性
    MT【177】三个乘积和
    MT【176】两两乘积
    MT【175】刚刚凑巧
    MT【174】凹凸无妨
    MT【173】齐次消元单变量
  • 原文地址:https://www.cnblogs.com/liuxueyang/p/3053577.html
Copyright © 2020-2023  润新知