zoukankan      html  css  js  c++  java
  • ZJOI2008 骑士

    题目描述:

    bz

    luogu

    题解:

    基环树+树形$dp$。

    每次找到一个联通块,对于环上的每个点向树的方向做树形$dp$。

    即$dp[i][0/1]$表示$i$点取/不取,$i$点子树内最大权。

    $pj$难度?

    然后拆环$dp$,讨论第一个点取还是不取。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 1000050;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,hed[N],cnt=1;
    ll w[N];
    bool use[N];
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    void bfs(int rt)
    {
        queue<int>q;
        q.push(rt);
        use[rt] = 1;
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int j=hed[u];j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(!use[to])
                {
                    use[to] = 1;
                    q.push(to);
                }
            }
        }
    }
    int sta[N],tl,rt;
    bool vis[N],cir[N];
    int dfs0(int u,int pre)
    {
        if(vis[u]){rt=u;return 1;}
        vis[u] = 1;
        for(int j=hed[u],now;j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(j==pre)continue;
            if((now=dfs0(to,j^1)))
            {
                if(now==1)
                {
                    sta[++tl] = u;
                    cir[u] = 1;
                    if(u!=rt)return 1;
                }
                return 2;
            }
        }
        return 0;
    }
    ll dp[N][2],s[N][2];
    void dfs(int u,int f)
    {
        dp[u][0] = 0,dp[u][1] = w[u];
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==f||cir[to])continue;
            dfs(to,u);
            dp[u][0]+=max(dp[to][0],dp[to][1]);
            dp[u][1]+=dp[to][0];
        }
    }
    ll sol(int z)
    {
        s[1][0]=dp[sta[1]][0],s[1][1]=(z?dp[sta[1]][1]:0);
        for(int i=2;i<=tl;i++)
        {
            s[i][0]=dp[sta[i]][0]+max(s[i-1][0],s[i-1][1]);
            s[i][1]=dp[sta[i]][1]+s[i-1][0];
        }
        return z?s[tl][0]:max(s[tl][0],s[tl][1]);
    }
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(n);
        for(int i=1,f;i<=n;i++)
        {
            read(w[i]),read(f);
            ae(f,i),ae(i,f);
        }
        ll ans = 0;
        for(int i=1;i<=n;i++)if(!use[i])
        {
            bfs(i);tl=0;
            dfs0(i,0);
            for(int j=1;j<=tl;j++)dfs(sta[j],0);
            ans+=max(sol(0),sol(1));
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    几种任务调度的 Java 实现方法与比较
    nginx配置
    生产消费_lock和阻塞队列
    阻塞队列
    countdownlatch+cyclicbarrier+semphore
    01背包
    skiplist
    lru
    按序打印_lock和condition
    按序打印_volatile 无法保证顺序
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10801620.html
Copyright © 2011-2022 走看看