Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
这么大的N,DFS为什么不会爆?In Reply To:雁过留声——缩强连通分量+dp Posted by:fanhqme at 2009-12-13 17:16:04 > dp的思路是很简单的:设dp[i]为走到第i个点后能够得到的最大值 > dp[i]=comfort[i]+Max{dp[j]|therer is edge(u,v)} > 然而,一旦遇到一个环,这个算法会re+tle,因为无限地递归计算。 > 怎么办呢? > > 经典的做法:缩强联通分量。 > 把所有的强联通分量缩成一个点,comfort为个点的comfort之和,然后再用dp > 这样,就不会遇到死循环的问题了。 > 这里,我为了方便,先把图用拓扑序排序一下,然后依次dp。 > > 关键代码: > struct edge{ > int e; > char type; > edge *next; > } > struct Graph{ > int N; > edge *E[NMax]; > int A[NMax]; > }G1,G2; > void dfs1(int a){ > vi[a]=1; > for (edge *p=G1.E[a];p;p=p->next) > if (p->type && !vi[p->e]) > dfs1(p->e); > rk[pt++]=a; > } > void dfs2(int a){ > belong[a]=pt; > for (edge *p=G1.E[a];p;p=p->next) > if (!p->type && belong[p->e]==-1) > dfs2(p->e); > } > void dfs3(int a){ > vi[a]=1; > for (edge *p=G2.E[a];p;p=p->next) > if (!vi[p->e]) > dfs3(p->e); > rk[pt++]=a; > } > > //拓扑排序 > pt=0; > for (int i=0;i<G1.N;i++)vi[i]=0; > for (int i=0;i<G1.N;i++)if (!vi[i]) > dfs1(i);//记录出栈序 > pt=0; > for (int i=0;i<G1.N;i++)belong[i]=-1; > for (int i=G1.N-1;i>=0;i--)if (belong[rk[i]]==-1){ > dfs2(rk[i]);//缩合,染色 > pt++; > } > > > //dp > for (int i=0;i<G2.N;i++)vi[i]=0; > pt=0; > for (int i=0;i<G2.N;i++)if (!vi[i]) > dfs3(i);//拓扑排序 > int tmp; > for (int i=0;i<G2.N;i++){ > x=rk[i]; > dp[x]=G2.A[x];tmp=0; > for (edge *p=G2.E[x];p;p=p->next) > tmp=(tmp<dp[p->e]?dp[p->e]:tmp); > dp[x]+=tmp; > } > int ret; > ret=0; > for (int i=0;i<G2.N;i++)if (ret<dp[i])ret=dp[i]; > printf("%d\n",ret); Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator