• TZOJ 3710 修路问题(最小差值生成树kruskal或者LCT)


    描述

    xxx国“山头乡”有n个村子,政府准备修建乡村公路,由于地形复杂,有些乡村之间可能无法修筑公路,因此政府经过仔细的考察,终于得到了所有可能的修路费用数据。并将其公布于众,广泛征求村民的修路意见。嗯,xxx国真是一个平等的国度。
    政府考虑到费用问题,因此要求只能建n-1条公路,而且这n-1条公路还能连通n个村子,而且调查数据表明,这完全是可行的。
    村民们展开了激烈的讨论,最后大家达成一致,要求每条路的费用要尽可能一样,这是基于“平等”的考虑,汗~
    xxx国政府头脑简单,这这,太难了,最后双方又达成一致,那就保证费用最大的那条与费用最小的那条之间的费用之差尽可能最小吧。
    现在的问题就交给你了,要你找出满足以上条件的一种方案,你只要输出费用最大的那条公路与费用最小的那条公路之间费用的差值w即可。嗯,因为这个数据还得告知村民,还是要“平等”。

    输入

    输入数据有多组。每组数据的第一行为两个整数n(2<n<=200)和m(m<=5000),表示村庄个数和可能的道路条数。
    接下来有m行,每行3个整数ai bi wi,分别表示村庄ai和村庄bi之间可以修一条路,需要费用为wi,这里村庄从1~n进行编号。wi<=100000000。

    输入以EOF结束,若不明白EOF结束的含义,请参考帮助

    输出

    每组数据在一行中输出一个整数,即题目描述中的w值。

    样例输入

    4 5
    1 2 1
    2 3 2
    1 3 3
    1 4 4
    3 4 5

    样例输出

    2

    题意

    求一颗生成树,使得最大边-最小边差值最小

    题解

    这里用的是kruskal,O(m^2)

    由于kruskal算法已经按边排序,所以最大边一定是最后加进去的那条

    然后可以枚举最小边,跑kruskal找到最后加进去的边(最大边)

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn=205;
     5 const int maxm=5005;
     6 
     7 struct edge
     8 {
     9     int u,v,w;
    10     bool operator<(const edge &D)const{
    11         return w<D.w;
    12     }
    13 }edges[maxm];
    14 
    15 int F[maxn];
    16 int Find(int x)
    17 {
    18     return F[x]==x?x:F[x]=Find(F[x]);
    19 }
    20 
    21 int main()
    22 {
    23     int n,m;
    24     while(cin>>n>>m)
    25     {
    26         for(int i=0,u,v,w;i<m;i++)
    27         {
    28             cin>>u>>v>>w;
    29             edges[i]=(edge){u,v,w};
    30         }
    31         sort(edges,edges+m);
    32         int Min=2e9;
    33         for(int i=0;i<m;i++)
    34         {
    35             int Max,cnt=0;
    36             for(int j=1;j<=n;j++)F[j]=j;
    37             for(int j=i;j<m;j++)
    38             {
    39                 edge &e=edges[j];
    40                 int fu=Find(e.u);
    41                 int fv=Find(e.v);
    42                 if(fu!=fv)
    43                 {
    44                     F[fu]=fv;
    45                     Max=e.w;
    46                     cnt++;
    47                 }
    48                 if(cnt==n-1)break;
    49             }
    50             if(cnt==n-1)Min=min(Min,Max-edges[i].w);
    51         }
    52         cout<<Min<<'
    ';
    53     }
    54     return 0;
    55 }
  • 相关阅读:
    [国家集训队]整数的lqp拆分
    来一波全套向量运算(C++)
    天哪又要搬家啦qvq
    利用输入输出流复制文件
    系统会随机给你两个日期(yyyy-MM-dd),求出两个日期的具体相差天数
    mysql中的连接操作
    java面试题集锦
    Java关于Math类的三个取整方法
    设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
    MySql5.5安装详细说明
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9544795.html
Copyright © 2020-2023  润新知