题目背景

缩点+DP

题目描述

给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

输入输出格式

输入格式:

第一行,n,m

第二行,n个整数,依次代表点权

第三至m+2行,每行两个整数u,v,表示u->v有一条有向边

输出格式:

共一行,最大的点权之和。

思路:

显然,由于点权为正,所以位于一个强连通分量中的结点,自然走得越多答案越大

所以,我们可以跑一边tarjan,将所有的强连通分量染色,建一个新的图

其中新图上的每个结点都代表旧图上的一个强连通分量

在跑tarjan染色的同时我们可以累加得到新图上每个点的点权

最后在新图上跑一边DP或者记忆化搜索即可

代码:

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #define rii register int i
  6. #define rij register int j
  7. using namespace std;
  8. struct yb{
  9. int from,to;
  10. }y[];
  11. struct ljb{
  12. int to,nxt;
  13. }x[];
  14. int tot,dq[],sta[],sum[],head[],bnt,last[];
  15. int n,m,dfn[],low[],top,cnt,vis[],color[],dp[];
  16. void add(int from,int to)
  17. {
  18. bnt++;
  19. x[bnt].to=to;
  20. if(head[from]==)
  21. {
  22. head[from]=bnt;
  23. }
  24. if(last[from]!=)
  25. {
  26. x[last[from]].nxt=bnt;
  27. }
  28. last[from]=bnt;
  29. }
  30. void search(int wz)
  31. {
  32. if(dp[wz]!=)
  33. {
  34. return;
  35. }
  36. dp[wz]=sum[wz];
  37. int maxn=;
  38. for(rii=head[wz];i!=;i=x[i].nxt)
  39. {
  40. int ltt=x[i].to;
  41. if(dp[ltt]==)
  42. {
  43. search(ltt);
  44. }
  45. maxn=max(maxn,dp[ltt]);
  46. }
  47. dp[wz]+=maxn;
  48. }
  49. void tarjan(int wz)
  50. {
  51. cnt++;
  52. low[wz]=cnt;
  53. dfn[wz]=cnt;
  54. top++;
  55. sta[top]=wz;
  56. vis[wz]=;
  57. for(rii=head[wz];i!=;i=x[i].nxt)
  58. {
  59. int ltt=x[i].to;
  60. if(dfn[ltt]==)
  61. {
  62. tarjan(ltt);
  63. low[wz]=min(low[wz],low[ltt]);
  64. }
  65. else
  66. {
  67. if(vis[ltt]==)
  68. {
  69. low[wz]=min(low[wz],dfn[ltt]);
  70. }
  71. }
  72. }
  73. if(dfn[wz]==low[wz])
  74. {
  75. tot++;
  76. while(sta[top+]!=wz)
  77. {
  78. color[sta[top]]=tot;
  79. sum[tot]+=dq[sta[top]];
  80. vis[sta[top]]=;
  81. top--;
  82. }
  83. }
  84. }
  85. int main()
  86. {
  87. scanf("%d%d",&n,&m);
  88. for(rii=;i<=n;i++)
  89. {
  90. scanf("%d",&dq[i]);
  91. }
  92. for(rii=;i<=m;i++)
  93. {
  94. scanf("%d%d",&y[i].from,&y[i].to);
  95. add(y[i].from,y[i].to);
  96. }
  97. for(rii=;i<=n;i++)
  98. {
  99. if(dfn[i]==)
  100. {
  101. tarjan(i);
  102. }
  103. }
  104. /*
  105. for(rii=1;i<=n;i++)
  106. {
  107. printf("%d ",color[i]);
  108. }
  109. cout<<endl;
  110. */
  111. bnt=;
  112. memset(head,,sizeof(head));
  113. memset(last,,sizeof(last));
  114. memset(x,,sizeof(x));
  115. for(rii=;i<=m;i++)
  116. {
  117. if(color[y[i].from]!=color[y[i].to])
  118. {
  119. add(color[y[i].from],color[y[i].to]);
  120. }
  121. }
  122. int ans=;
  123. for(rii=;i<=n;i++)
  124. {
  125. if(dp[i]==)
  126. {
  127. search(i);
  128. }
  129. ans=max(ans,dp[i]);
  130. }
  131. printf("%d\n",ans);
  132. }

【模板】缩点(tarjan,DAG上DP)的更多相关文章

  1. bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp

    一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...

  2. [正经分析] DAG上dp两种做法的区别——拓扑序与SPFA

    在下最近刷了几道DAG图上dp的题目. 要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点. 第二道是洛谷上的NOI导刊题目<最长路 ...

  3. DAG上dp思想

    DAG上DP的思想 在下最近刷了几道DAG图上dp的题目.要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点.第二道是洛谷上的NOI导刊题 ...

  4. BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]

    方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...

  5. [CF225C] Barcode (简单DAG上dp)

    题目链接:http://codeforces.com/problemset/problem/225/C 题目大意:给你一个矩阵,矩阵中只有#和.两种符号.现在我们希望能够得到一个新的矩阵,新的矩阵满足 ...

  6. bzoj1179: [Apio2009]Atm scc缩点+dag上dp

    先把强连通缩点,然后变成了dag,dp求终点是酒吧的最长路即可, /************************************************************** Pro ...

  7. EOJ Monthly 2019.2 E 中位数 (二分+中位数+dag上dp)

    题意: 一张由 n 个点,m 条边构成的有向无环图.每个点有点权 Ai.QQ 小方想知道所有起点为 1 ,终点为 n 的路径中最大的中位数是多少. 一条路径的中位数指的是:一条路径有 n 个点,将这  ...

  8. UVA 437 巴比伦塔 【DAG上DP/LIS变形】

    [链接]:https://cn.vjudge.net/problem/UVA-437 [题意]:给你n个立方体,让你以长宽为底,一个个搭起来(下面的立方体的长和宽必须大于上面的长和宽)求能得到的最长高 ...

  9. uva 437 巴比伦塔(DAG上dp)

    巴比伦塔 紫书P269 看完紫书,终于可以自己写一个dp了 :) [题目链接]巴比伦塔 [题目类型]DAG上dp &题意: 有n种立方体 n<=30,每种有无穷个,要求选一些立方体摞成一 ...

随机推荐

  1. html简介(自己理解和老师讲课)

    首先讲开发网页三种技术:html,css,javascript.html负责网页的结构,css站在没学角度对网页进行美化,javascript负责网页交互,站在用户体验角度设计网页交互效果 而我们所学 ...

  2. 新手必需用!大道至简的前端编辑器Sublime Text

    很多人在进入学习前端的时候(包括我自己),除了选择学习合适的技术,还需要一个得(自)心(己)应(喜)手(欢)的开发工具,一个得心应手的开发工具除了可以令你的效率大大提高,也可以令你在写代码的时候,心情 ...

  3. input框中如何添加搜索

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 关于Telnet使用

    一.telnet作用 可以使用telnet检查 ip port的连通性 语法: telnet ip port 注意点: 1.使用前先操作系统安装telnet: 2.ip port 中间没有 “:”: ...

  5. Visual C++编程实现摄像头视频捕捉

    原文:http://blog.csdn.net/nemojiang/article/details/653033?locationNum=7&fps=1 前言 DirectShow是微软公司提 ...

  6. 【Machine Learning】监督学习、非监督学习及强化学习对比

    Supervised Learning Unsupervised Learning Reinforced Learning Goal: How to apply these methods How t ...

  7. 深度解析pos机,养卡人必看!

    好多人对POS 好像都比较迷茫,这个说这个POS 好,那个说那个POS 好.下面就我对POS 的认知给兄弟们说下.对与不对的各位见谅.   第一.一清机 一清机是指在结算日结算后直接通过支付公司账号转 ...

  8. Google play billing(Google play 内支付) 下篇

    开篇: 如billing开发文档所说,要在你的应用中实现In-app Billing只需要完成以下几步就可以了. 第一,把你上篇下载的AIDL文件添加到你的工程里,第二,把 <uses-perm ...

  9. dbms_randon package

    reference to wbsite:http://zhangzhongjie.iteye.com/blog/1948930#comments DBMS_RANDON PACKAGE: Define ...

  10. 使用mysli防止sql注入

    自从 php5 推出 mysqli 后就开始不提倡使用 mysql_ 开头的接口了,现在使用 mysql_connet 通常调试的时候会报警告说这个不该用 mysqli 使用起来其实更简单 $url ...