见题:
看一眼,就知道是个依赖性背包,于是乎就草草的打了树上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; }
以后看题还需仔细了...