Tarjan+topsort(DP)【P3387】 [模板]缩点
2018-11-03 06:53
399 查看
Description
给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
Input
第一行,n,m
第二行,n个整数,依次代表点权
第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
Output
共一行,最大的点权之和。
缩点+DP这是题目说的
先缩点,对于每一个联通块之间建边,这时得到一张\(DAG\)(有向无环图)
我们对其跑拓扑排序,然后开一个数组\(dis\)记录到达某个点的最大值.
对于那些入度为0的点,我们初始化其\(dis\)为其联通块的点权之和.
然后每次取\(max\)即可.
最终\(ans\)即为对到达每个点的\(dis\)取\(max\)。
代码
#include<cstdio> #include<iostream> #include<algorithm> #define R register using namespace std; const int gz=50008; inline void in(int &x) { int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f; } int head[gz],tot,val[gz],v[gz],h[gz],dis[gz],ins[gz],ans,n,m; struct cod{int u,v;}edge[gz<<1],e[gz<<1]; inline void add(R int x,R int y) { edge[++tot].u=head[x]; edge[tot].v=y; head[x]=tot; } inline void ado(R int x,R int y) { e[++tot].u=h[x]; e[tot].v=y; h[x]=tot; } int dfn[gz],belong[gz],idx,low[gz],stk[gz],top,col; bool inq[gz]; void tarjan(R int x) { low[x]=dfn[x]=++idx; stk[++top]=x;inq[x]=true; for(R int i=head[x];i;i=edge[i].u) { if(!dfn[edge[i].v]) { tarjan(edge[i].v); low[x]=min(low[x],low[edge[i].v]); } else if(inq[edge[i].v]) low[x]=min(low[x],dfn[edge[i].v]); } if(low[x]==dfn[x]) { int now=-1; col++; while(now!=x) { now=stk[top--]; belong[now]=col; inq[now]=false; v[col]+=val[now]; } } } inline void topsort() { top=0; for(R int i=1;i<=col;i++) if(!ins[i])stk[++top]=i,dis[i]=v[i]; while(top) { int u=stk[top--]; for(R int i=h[u];i;i=e[i].u) { ins[e[i].v]--; dis[e[i].v]=max(dis[e[i].v],dis[u]+v[e[i].v]); if(!ins[e[i].v])stk[++top]=e[i].v; } } for(R int i=1;i<=col;i++) ans=max(ans,dis[i]); printf("%d\n",ans); } int main() { in(n),in(m); for(R int i=1;i<=n;i++)in(val[i]); for(R int i=1,x,y;i<=m;i++) { in(x),in(y); add(x,y); } for(R int i=1;i<=n;i++) if(!dfn[i])tarjan(i); tot=0; for(R int i=1;i<=n;i++) for(R int j=head[i];j;j=edge[j].u) if(belong[i]!=belong[edge[j].v]) { ins[belong[edge[j].v]]++; ado(belong[i],belong[edge[j].v]); } topsort(); }
相关文章推荐
- Tarjan 缩点模板(洛谷P3387)
- tarjan模板(缩点,求有向图强连通分量)
- 硬币问题 tarjan缩点+DP 莫涛
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(最近公共祖先)
- Tarjan 缩点(P3387)
- tarjan【模板】缩点
- 有向图tarjan 求桥 + 求SCC以及里面的点和它的入度 +缩点 模板 【总结】
- 洛谷 P3387 【模板】缩点
- 洛谷 P3387 【模板】缩点
- 模板_tarjan强连通缩点算法
- 洛谷P2341 受欢迎的牛——Tarjan+缩点模板
- 【模板】Tarjan缩点,强连通分量 洛谷P2341 [HAOI2006]受欢迎的牛 [2017年6月计划 强连通分量01]
- BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
- NOIP2009最优贸易[spfa变形|tarjan 缩点 DP]
- BZOJ 2208 [Jsoi2010]连通数 tarjan缩点+bitset优化DP
- 浅谈Tarjan缩点(分析+模板)
- BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(近期公共祖先)
- 【模板】Tarjan 缩点 + 最长路
- bzoj 2427: [HAOI2010]软件安装(tarjan缩点+树形dp)