图论.DP

见题:

看一眼,就知道是个依赖性背包,于是乎就草草的打了树上DP,一交发现才20,仔细检查也没错呀,忍不住点了题解,只喵一眼看到了强联通缩点等的字样,又重新审了一遍题,发现这句话理解有偏差:软件i只有在安装了软件j(包括软件j的直接或间接依赖)。题目并未说i依赖j时,j就不能依赖i了,所以就形成了环了。

代码:

#include<bits/stdc++.h>
#define max(a,b) (((a)>(b))?(a):(b))
#define min(a,b) (((a)<(b))?(a):(b))
using namespace std;
const int MAXN=510,maxn=110;
vector<int>son[maxn];
int tot,low[maxn],dfn[maxn],link[maxn],stackn[maxn],vis[maxn],top,o;
int n,w[maxn],v[maxn],m,c,ans[maxn],ww[maxn],vv[maxn],ru[maxn],f[maxn][MAXN]; 
struct bian
{
    int y,next;
};
bian a[100000];
inline int read()
{
    int x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-') ff=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*ff;
}
inline void put(int x)
{
    if(x<0) putchar('-'),x=-x;
    if(x>9) put(x/10);
    putchar(x%10+'0');
}
inline void add(int x,int y)
{
    a[++tot].y=y;
    a[tot].next=link[x];
    link[x]=tot;
}
inline void tarjan(int x)
{
    dfn[x]=low[x]= ++o;
    vis[stackn[++top]=x]=1;
    for(int i=link[x];i;i=a[i].next)
    {
        int y=a[i].y;
        if(!dfn[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(vis[y]) low[x]=min(dfn[y],low[x]);
    }
    if(dfn[x]==low[x])
    {
        int k;c++;
        do{
            vis[k=stackn[top--]]=0;
            ans[k]=c;
        }while(k!=x);
    }
}
inline void dfs(int x)
{
    for(int i=ww[x];i<=m;i++)f[x][i]=vv[x];
    for(int i=0;i<son[x].size();i++)
    {
        int y=son[x][i];
        dfs(y);
        for(int t=m;t>=ww[x];t--)                       
        {
            for(int k=0;k<=t-ww[x];k++) f[x][t]=max(f[x][t],f[x][t-k]+f[y][k]);
        }
    }
}
int main()
{
    freopen("1.in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=n;i++) w[i]=read();
    for(int i=1;i<=n;i++) v[i]=read();
    for(int i=1;i<=n;i++)
    {
        int x=read();
        if(x) add(x,i);
    }
    for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i++) ww[ans[i]]+=w[i],vv[ans[i]]+=v[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=link[i];j;j=a[j].next)
        {
            if(ans[i]==ans[a[j].y]) continue;
            son[ans[i]].push_back(ans[a[j].y]);ru[ans[a[j].y]]++;
        }
    }
    for(int i=1;i<=c;i++) if(!ru[i]) son[0].push_back(i);
    dfs(0);
    put(f[0][m]);
    return 0;
}

以后看题还需仔细了...

原文地址:https://www.cnblogs.com/gcfer/p/10607065.html