bzoj2427: [HAOI2010]软件安装

一开始的想法:top判一下环,然后直接D

然后其实整个环一起取是合法的

所以无脑缩点

然而森林转二叉树+treedp真的慢到爆炸,10s跑不出一个点

Rose:我从来都是直接多叉D  (%%%%%%

然后就%了一发fyc,然后学会了。(或许某天我又会回来补)

 

垃圾森林转二叉

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct node
{
    int x,y,next;
}a[510];int len,last[110];
void eins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}

int z,dfn[110],low[110];
int top,sta[110];bool V[110];
int cnt,belong[110];
void strong_unicom(int x)
{
    dfn[x]=low[x]=++z;
    sta[++top]=x;V[x]=true;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dfn[y]==0)
        {
            strong_unicom(y);
            low[x]=min(low[x],low[y]);
        }
        else
        {
            if(V[y]==true)
                low[x]=min(low[x],dfn[y]);
        }
    }
    if(low[x]==dfn[x])
    {
        int i;cnt++;
        do
        {
            i=sta[top];top--;
            V[i]=false;
            belong[i]=cnt;
        }while(i!=x);
    }
}

//---------strong unicom-------

struct tree
{
    int lc,rc;
}tr[110];int rit[510];
void ins(int x,int y)
{
    if(rit[x]!=0)
    {
        int t=rit[x];
        rit[x]=y;
        x=t;
        
        tr[x].rc=y;
    }
    else tr[x].lc=y, rit[x]=y;
}

int n;
int w[510],v[510],d[510];
int nw[110],nv[110],nd[110];
void composition()
{
    nw[0]=nv[0]=0;
    for(int i=1;i<=n;i++)
    {
        nw[belong[i]]+=w[i];
        nv[belong[i]]+=v[i];
        if(belong[d[i]]!=belong[i])nd[belong[i]]=belong[d[i]];
    }
    memset(rit,0,sizeof(rit));
    for(int i=1;i<=cnt;i++)
        if(nd[i]==0)
            ins(cnt+1,i);
        else 
            ins(nd[i],i);
            
}

//-------composition----------

int f[110][510];
void dfs(int x,int m)
{
    if(f[x][m]!=0)return ;
    if(tr[x].lc==0&&tr[x].rc==0)return ;
    
    for(int i=0;i<=m;i++)//分给兄弟 
    {
        int sum=0;
        int d=m-i;
        if(d>=nw[x])
        {
            sum+=nv[x];
            if(tr[x].lc!=0)
            {
                dfs(tr[x].lc,d-nw[x]);
                sum+=f[tr[x].lc][d-nw[x]];
            }
        }
        if(tr[x].rc!=0)
        {
            dfs(tr[x].rc,i);
            sum+=f[tr[x].rc][i];
        }
        f[x][m]=max(f[x][m],sum);
    }
}

//---treeDP--------

int main()
{
    int m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&d[i]);
        eins(d[i],i);
    }
    
    z=top=cnt=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(belong,0,sizeof(belong));
    memset(V,false,sizeof(V));
    for(int i=1;i<=n;i++)
        if(dfn[i]==0)
            strong_unicom(i);
    composition();
    
    memset(f,0,sizeof(f));
    dfs(cnt+1,m);
    printf("%d\n",f[cnt+1][m]);
    return 0;
}

 

AC:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct node
{
    int x,y,next;
}e[510];int elen,elast[110];
void eins(int x,int y)
{
    elen++;
    e[elen].x=x;e[elen].y=y;
    e[elen].next=elast[x];elast[x]=elen;
}

int z,dfn[110],low[110];
int top,sta[110];bool V[110];
int cnt,belong[110];
void strong_unicom(int x)
{
    dfn[x]=low[x]=++z;
    sta[++top]=x;V[x]=true;
    for(int k=elast[x];k;k=e[k].next)
    {
        int y=e[k].y;
        if(dfn[y]==0)
        {
            strong_unicom(y);
            low[x]=min(low[x],low[y]);
        }
        else
        {
            if(V[y]==true)
                low[x]=min(low[x],dfn[y]);
        }
    }
    if(low[x]==dfn[x])
    {
        int i;cnt++;
        do
        {
            i=sta[top];top--;
            V[i]=false;
            belong[i]=cnt;
        }while(i!=x);
    }
}

//---------strong unicom-------

node a[510];int len,last[510];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}

int n;
int w[510],v[510],d[510];
int nw[110],nv[110],nd[110];
void composition()
{
    nw[0]=nv[0]=0;
    for(int i=1;i<=n;i++)
    {
        nw[belong[i]]+=w[i];
        nv[belong[i]]+=v[i];
        if(belong[d[i]]!=belong[i])nd[belong[i]]=belong[d[i]];
    }
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=cnt;i++)
        if(nd[i]==0)
            nd[i]=cnt+1, ins(nd[i],i);
        else 
            ins(nd[i],i);
            
}

//-------composition----------

int m,g[110],f[110][510];
void dfs(int x)
{
    g[x]=g[nd[x]]+nw[x];
    for(int i=m;i>=g[x];i--)
        f[x][i]=max(f[x][i],f[nd[x]][i-nw[x]]+nv[x]);
    for(int k=last[x];k;k=a[k].next)dfs(a[k].y);
    int fa=nd[x];
    for(int fa=nd[x];fa;fa=nd[fa])
        for(int i=0;i<=m;i++)f[fa][i]=max(f[fa][i],f[x][i]);
}

//---treeDP--------

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    for(int i=1;i<=n;i++)scanf("%d",&v[i]);
    elen=0;memset(elast,0,sizeof(elast));
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&d[i]);
        eins(d[i],i);
    }
    
    z=top=cnt=0;
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(belong,0,sizeof(belong));
    memset(V,false,sizeof(V));
    for(int i=1;i<=n;i++)
        if(dfn[i]==0)
            strong_unicom(i);
    composition();
    
    memset(f,0,sizeof(f));
    dfs(cnt+1);
    printf("%d\n",f[cnt+1][m]);
    return 0;
}

 

posted @ 2018-03-08 20:07  AKCqhzdy  阅读(225)  评论(0编辑  收藏  举报