zoukankan      html  css  js  c++  java
  • hdu4424 并查集+贪心+思维

    #include<bits/stdc++.h>
    #define MAXN 200005
    using namespace std;
    
    long long n,tot;
    long long f[MAXN],cnt[MAXN],ans[MAXN];
    struct node{
        long long from,to,cost,next,tp;
    }e[MAXN<<1]; 
    
    void init(){
        tot=0;
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)f[i]=i,cnt[i]=1;
    }
    
    void add(long long x,long long y,long long z){
        tot++;
        e[tot].from=x;
        e[tot].to=y;
        e[tot].cost=z;
    }
    
    long long found(long long x){
        if(f[x]==x)return x;
        int fa=found(f[x]);
        f[x]=fa;
        return fa;
    }
    
    bool cmp(node x,node y){
        return x.cost>y.cost;
    }
    
    int main(){
        while(scanf("%lld",&n)==1){
            init();
            for(int i=1;i<n;i++){
                long long x,y,z;
                scanf("%lld%lld%lld",&x,&y,&z);
                add(x,y,z);    
            }
            sort(e+1,e+1+tot,cmp);
            for(int i=1;i<n;i++){
                long long ff=found(e[i].from),fy=found(e[i].to);
                if(ff!=fy){
                    if(ans[fy]+cnt[ff]*e[i].cost>ans[ff]+cnt[fy]*e[i].cost)swap(ff,fy);
                    ans[ff]+=(cnt[fy]*e[i].cost);
                    cnt[ff]+=cnt[fy];
                    f[fy]=ff;
                }
            }
            cout<<ans[found(1)]<<endl;
        }
    }
    View Code

    一开始有点想法....

    .................. 

    嘛,仔细分析一下,发现可以在最小值最大哪里搞一下.....

    尝试从小到大枚举每条边....发现这样答案可以计算(就是一个分治的过程....每次选择与这条边相连的两点(怎么说呢)就是舍去一段子树....差不多了吧)

    或者贪心好像也行把....每次把节点数小的给删掉....(显然满足题目要求把....).

    然后考虑怎么解决一条边是否已经再被删掉的子树里面出现....

    直接并查集维护一下每个边左右子树的根....要删掉那一个就把它的根标记一下就好了.....但是不能路径压缩,,,,(显然把....)

    但是,,上面做法会t飞

    于是乎,再度分析...

    不如从最大值考虑?

    于是乎,,,,,,发现,一些较大边对于答案没有贡献啊!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    那么我们要它干嘛,直接删掉.....考虑删掉后咋办....把两个点合并呗.....

    对于没有贡献的边怎么合并都无所谓啦......

    但是对于有贡献的就要考虑,既然是要最大化答案,,,,,当然是按照可以使得答案最大的来搞(感觉自己好多废话)

    于是乎就清晰了

    1 从大到小排序

    2 然后依次合并点集....

    然后这题就结束了

    ------------------------------------------------------------------------------------------------------------------------------------------------------------

    经验:

    1 仔细分析题目啊!!!!!!!

    2 遇到难搞(会炸)的地方要考虑影藏性质

    3.不能应为感觉思考出一个假的正解(没AC)就沾沾自喜 去颓

  • 相关阅读:
    [CERC2016]机棚障碍 Hangar Hurdles(kruskal重构树+树上倍增)
    jzoj4313 电话线铺设(最小生成树+最近公共祖先)
    POJ3233 Matrix Power Series(快速幂求等比矩阵和)
    【模版】分治法求平面最近点对
    [HNOI2009]最小圈 (二分答案+负环)
    [USACO]地震 (二分答案+最优比率生成树详解)
    BZOJ:1816 [Cqoi2010]扑克牌 (贪心或二分答案)
    bzoj 4184: shallot (线段树维护线性基)
    一维点距的中位数 (分治)
    [BJWC2011]最小三角形(分治+最近点对)
  • 原文地址:https://www.cnblogs.com/shatianming/p/12295900.html
Copyright © 2011-2022 走看看