zoukankan      html  css  js  c++  java
  • tyvj1940创世纪——贪心(基环树)

    题目:http://www.joyoi.cn/problem/tyvj-1940

    基环树的样子,看了书上的讲解,准备写树上DP,然后挂了:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const MAXN=1e6+5,inf=1e9;
    int n,a[MAXN],f[MAXN][3],head[MAXN],ct,s[MAXN],h,col[MAXN],cr,rt,ans;
    int sta[MAXN],top,reg[MAXN];
    bool in[MAXN],fl,vis[MAXN];
    struct N{
        int to,next;
        N(int t=0,int n=0):to(t),next(n) {}
    }edge[MAXN];
    void add(int x,int y)
    {
        edge[++ct]=N(y,head[x]);head[x]=ct;
        edge[++ct]=N(x,head[y]);head[y]=ct;
    }
    void ser(int x)
    {
        col[x]=cr;
        for(int i=head[x],u;i;i=edge[i].next)
            if(!col[u=edge[i].to])ser(u);
    }
    void tj(int rt,int x)
    {
        if(fl)return;
        sta[++top]=x;vis[x]=1;
        for(int i=head[x],u;i;i=edge[i].next)
        {
            if(edge[i].to==a[x])continue;
            if(!vis[u=edge[i].to])tj(rt,u);
            else
            {
                while(sta[top]!=rt)
                {
                    int t=sta[top];
                    s[++h]=t;
                    in[t]=1;top--;
                }
                in[rt]=1;s[++h]=rt;top--;
                fl=1;return;
            }
        }
        top--;
    }
    void dfs(int x)
    {
        int mn=inf,sum=0;
        for(int i=head[x],u;i;i=edge[i].next)
        {
            u=edge[i].to;
            if(u==rt)continue;
            if(u==a[x]||col[u]!=col[x])continue;
            dfs(u);
            f[x][0]+=max(f[u][0],f[u][1]);
            sum+=f[u][1];
            mn=min(mn,f[u][1]-f[u][0]);
        }
        if(sum==0)f[x][1]=1;
        else f[x][1]=sum-mn;
    }
    void dfs2(int x)
    {
        int mn=inf,sum=0;
        for(int i=head[x],u;i;i=edge[i].next)
        {
            u=edge[i].to;
            if(u==rt)continue;
            if(u==a[x]||col[u]!=col[x])continue;
            dfs(u);
            f[x][0]+=max(f[u][0],f[u][1]);
            sum+=f[u][1];
            mn=min(mn,f[u][1]-f[u][0]);
        }
        if(sum==0)f[x][1]=1;
        else if(x==a[rt])f[x][1]=sum;
        else f[x][1]=sum-mn;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            reg[i]++;reg[a[i]]++;
            add(i,a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            if(!col[i])h=1,cr++,ser(i);
            int rt;fl=0;int s=0;
            for(int j=1;j<=n;j++)
                if(reg[j]>2&&col[j]==cr)
                    {rt=j;break;}
            tj(rt,i);
            dfs(rt);
            s=max(f[rt][1],f[rt][0]);
            dfs2(rt);
            s=max(s,f[rt][1]);
            ans+=s;
        }
        printf("%d",ans);
        return 0;
    }
    无输出的冗长树上DP

    题目挺有意思,自己本来也想过贪心的做法,但不会处理链与环交接处的问题,想不清楚一条链会对环有什么影响;

    然后看了看别人的博客,才发现链对环没有影响。。。因为环上的点不论链上怎样,仍还有环上别的点限制它;

    所以链与环都是隔一个选一个,贪心。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    queue<int>q;
    int const MAXN=1e6+5;
    int n,a[MAXN],reg[MAXN],ans;
    bool vis[MAXN],v2[MAXN];
    void bfs()
    {
        for(int i=1;i<=n;i++)
            if(!reg[i])q.push(i);
        while(q.size())
        {
            int x=q.front();q.pop();
            vis[x]=1;
            if(!vis[a[x]])
            {
                ans++;//因为多起点开始,不方便直接求链的长度,所以一个一个加
                vis[a[x]]=1;
                reg[a[a[x]]]--;
                if(!reg[a[a[x]]]&&!vis[a[a[x]]])
                    q.push(a[a[x]]);
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            reg[a[i]]++;
        }
        bfs();
        for(int i=1;i<=n;i++)
            if(!vis[i]&&!v2[i])
            {
                int cnt=1;v2[i]=1;
                int j=a[i];
                while(!v2[j])cnt++,j=a[j];
                ans+=cnt/2;
            }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    并发编程知识点剖析
    JavaScript 实现留言框
    JavaScript 实现简单的 弹出框关闭框
    网络编程知识点剖析
    css清除浮动的方法
    css盒模型
    CSS的继承性和层叠性
    转载《ionic 热更新 cordova-hot-code-push》
    转《js闭包与内存泄漏》
    前端存储loaclForage
  • 原文地址:https://www.cnblogs.com/Zinn/p/8948205.html
Copyright © 2011-2022 走看看