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 |
雁过留声——缩强连通分量+dpdp的思路是很简单的:设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