今天早上起来状态不如昨天,上来就做软件安装:
这题上来就知道是反向建边,然后跑树批(树上dp)然后就开始码,并没有看标签,以为这就是上天赐予的水题,满怀信心要AC他,dp式子也写对了,也建虚根节点了,然而
惊喜爆10,一看标签,省选,靠,不是水题(宝宝不开心!)然后就想了一想,自己又手膜了一个样例然后就发现会出现环,例如1 3 2 1时就会出现环,所以需要什么?
tarjin(orz)缩点啊,然后,然后就A了;
码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<stack> 6 using namespace std; 7 #define LL long long 8 //powered by lsc; 9 const LL maxn=8000; 10 LL head[maxn],ver[maxn],nxt[maxn],tot,d[maxn],cntt; 11 struct chu{ 12 LL x,y,head,nxt; 13 }s[maxn]; //edge; 14 15 LL w[maxn],v[maxn],dp[3000][3000]; 16 LL n,m,ans; //problom; 17 18 LL dfn[maxn],low[maxn],belong[maxn],cp[maxn],cnt,vis[maxn],cw[maxn];//cp is the v value,cw is the w value; 19 stack<LL>ss; 20 inline void add(LL x,LL y){ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;} 21 inline void ADD(LL x,LL y){s[++cntt].y=y;s[cntt].x=x;s[cntt].nxt=s[x].head;s[x].head=cntt;} 22 void dfs(LL x) 23 { 24 dfn[x]=low[x]=++cnt; 25 ss.push(x); 26 vis[x]=1; 27 for (LL i=s[x].head;i;i=s[i].nxt) 28 if (!dfn[s[i].y]) 29 dfs(s[i].y), 30 low[x]=min(low[x],low[s[i].y]); 31 else if (vis[s[i].y]) 32 low[x]=min(low[x],dfn[s[i].y]); 33 if (dfn[x]==low[x]) 34 { 35 cp[x]=0;LL ress=0; 36 for (LL y=-1;y!=x;y=ss.top(),ss.pop()) 37 { 38 belong[ss.top()]=x, 39 cp[x]+=v[ss.top()], 40 cw[x]+=w[ss.top()], 41 vis[ss.top()]=0; 42 } 43 } 44 } 45 void solve(LL x,LL fa) 46 { 47 for(LL i=cw[x];i<=m;i++) 48 dp[x][i]=cp[x]; 49 for(LL i=head[x];i;i=nxt[i]) 50 { 51 LL y=ver[i]; 52 if(y==fa)continue;solve(y,x); 53 for(LL o=m-cw[x];o>=0;o--) 54 for(LL u=0;u<=o;u++) 55 dp[x][o+cw[x]]=max(dp[x][o+cw[x]],dp[y][u]+dp[x][o+cw[x]-u]); 56 } 57 } 58 int main() 59 { 60 //freopen("cnm.txt","r",stdin); 61 scanf("%lld%lld",&n,&m); 62 for(LL i=1;i<=n;i++) 63 scanf("%lld",&w[i]); 64 for(LL i=1;i<=n;i++) 65 scanf("%lld",&v[i]); 66 for(LL i=1;i<=n;i++){LL vp=0;scanf("%lld",&vp);if(vp==0)continue;ADD(vp,i);} 67 //for(LL i=1;i<=n;i++)if(d[i]==0)ADD(0,i); //xu root; 68 for(LL i=1;i<=n;i++)if(!dfn[i])dfs(i); 69 for(LL j=1;j<=cnt;j++) 70 { 71 if(belong[s[j].x]!=belong[s[j].y]) 72 //printf("%d %d start point value:%d end point value:%d\n",belong[i],belong[s[j].y],cw[belong[i]],cw[belong[s[j].y]]), 73 add(belong[s[j].x],belong[s[j].y]), 74 d[belong[s[j].y]]++; 75 } 76 for(int i=1;i<=n;i++)if(d[i]==0)add(0,i); 77 solve(0,0); 78 printf("%lld\n",dp[0][m]); 79 return 0; 80 }
//////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////未完待更///////////////////////////////////////////////////////////////////
原文:https://www.cnblogs.com/hzoi-lsc/p/11176107.html