• bzoj1040(ZJOI2008)骑士——基环树


    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1040

    基环树的模板。

    套路就是把环断开,先把一端作为根节点,强制不选;再把另一端作为根节点,强制不选。

    人家的这个判断环的方法真好!还顺便没有连上环的那条边,省下了在函数里判断。

    别忘了有多棵基环树!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int N=1e6+5;
    int n,m,head[N],xnt,fa[N],rta[N],rtb[N];
    ll dp[N][2],a[N],ans;
    struct Edge{
        int next,to;
        Edge(int n=0,int t=0):next(n),to(t) {}
    }edge[N<<1];
    int find(int a){return fa[a]==a?a:fa[a]=find(fa[a]);}
    void add(int a,int b)
    {
        edge[++xnt]=Edge(head[a],b);head[a]=xnt;
        edge[++xnt]=Edge(head[b],a);head[b]=xnt;
        fa[find(a)]=find(b);
    }
    void sol(int cr,int fa)
    {
        dp[cr][1]=a[cr];dp[cr][0]=0;
        for(int i=head[cr],v;i;i=edge[i].next)
        {
            v=edge[i].to;
            if(v==fa)continue;
            sol(v,cr);
            dp[cr][0]+=max(dp[v][0],dp[v][1]);
            dp[cr][1]+=dp[v][0];
        }
    }
    int main()
    {
        scanf("%d",&n);int tmp;
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld%d",&a[i],&tmp);
            if(find(i)!=find(tmp))
                add(i,tmp);
            else rta[++m]=i,rtb[m]=tmp;
        }
        ll c;
        for(int i=1;i<=m;i++)
        {
            sol(rta[i],0);c=dp[rta[i]][0];
            sol(rtb[i],0);c=max(c,dp[rtb[i]][0]);
            ans+=c;
        }
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    Cesium加载倾斜摄影数据
    CentOS7安装Docker
    Docker镜像下载
    c#验证密码强度
    配置阿里yum源
    ftpbat脚本
    powershell-ftpmove文件到本地
    Session Setup Request,NTLMSSP_AUTH, User:Dmainhostname$
    smblog
    树莓派显示器屏幕休眠
  • 原文地址:https://www.cnblogs.com/Narh/p/9136465.html
Copyright © 2020-2023  润新知