zoukankan      html  css  js  c++  java
  • luogu P2700 逐个击破

    思维题,套路题。

    本来想在学完树形dp,开始做数据结构前刷几道水题愉悦一下身心,结果tm直接匹配了一道不用树形dp十分有意思的题

    思路:考虑题目的转化:将删除的边数最小转化为留下的权值最大,用kruskal的思想加边,如果两点都是敌人直接切,如果一方是敌人,先不管,将另一方感染为敌人。这也是拆边连通性问题的一般思路。

    code:

    #include<bits/stdc++.h>
    #define IL inline
    #define RI register int
    IL void in(int &x)
    {
        int f=1;x=0;char s=getchar();
        while(s>'9' or s<'0'){if(s=='-')f=-1;s=getchar();}
        while(s>='0' and s<='9'){x=x*10+s-'0';s=getchar();}
        x*=f;
    }
    int n,k,f[100008],tot;
    bool init[1000008];
    long long ans;
    struct cod{int u,v,w;}edge[100008];
    IL int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    IL bool ccp(const cod&a,const cod&b){return a.w>b.w;}
    int main(void)
    {
        in(n),in(k);
        for(RI i=1;i<=n;i++)f[i]=i;
        for(RI i=1,x;i<=k;i++)in(x),init[x]=true;
        for(RI i=1;i<=n-1;i++)
            in(edge[i].u),in(edge[i].v),in(edge[i].w),ans+=edge[i].w;
        std::sort(edge+1,edge+n,ccp);
        for(RI i=1;i<=n-1;i++)
        {
            int u=edge[i].u,v=edge[i].v,w=edge[i].w;
            int fu=find(u),fv=find(v);
            if(init[fu] and init[fv])continue;
            f[fu]=fv;
            ans-=w;
        }
        printf("%lld",ans);
    }
    

    收获:有时用并查集可以解决这类连通性问题(路径压缩),还有注意题目的转化

  • 相关阅读:
    pandas isin 和not in
    游戏开发需要学什么?
    打开页面,数字会自增的效果怎么弄?
    jq 导航栏点击添加/删除类(a标签跳转页面)
    bootstrap+jq分页
    2020/12/18
    2020/12/17
    2020/12/16
    2020/12/15
    2020/12/14
  • 原文地址:https://www.cnblogs.com/bullshit/p/9643135.html
Copyright © 2011-2022 走看看