题目背景

缩点+DP

题目描述

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

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

输入输出格式

输入格式:

第一行,n,m

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

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

输出格式:

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

输入输出样例

输入样例#1: 复制

  1. 2 2
  2. 1 1
  3. 1 2
  4. 2 1

输出样例#1: 复制

  1. 2

说明

n<=104,m<=105,|点权|<=1000 算法:Tarjan缩点+DAGdp`

如题,DAG图dp有一个很显然的思路--拓扑排序

  1. #include<stack>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. const int maxn = 100007;
  6. int vul[maxn];
  7. struct node{
  8. int v,next;
  9. }edge[maxn*5],edge1[maxn*5];
  10. int head1[maxn],num1;
  11. int head[maxn],num;
  12. void add_edge(int u,int v) {
  13. edge[++num].v=v;edge[num].next=head[u];head[u]=num;
  14. }
  15. void add_edge1(int u,int v) {
  16. edge1[++num1].v=v;edge1[num1].next=head1[u];head1[u]=num1;
  17. }
  18. int n,m,cnt =0,dfn[maxn],low[maxn];bool vis[maxn];
  19. int stack[maxn],top=0;
  20. int vulue[maxn],sum,belong[maxn];
  21. void tarjan(int x) {
  22. low[x]=dfn[x]=++cnt;stack[++top]=x;
  23. vis[x]=1;
  24. for(int i=head[x];i;i=edge[i].next) {
  25. int v=edge[i].v;
  26. if(vis[v]) {
  27. low[x]=std::min(low[x],dfn[v]);
  28. }
  29. else if(!dfn[v]){
  30. tarjan(v);
  31. low[x]=std::min(low[x],low[v]);
  32. }
  33. }
  34. if(low[x]==dfn[x]) {
  35. sum++;
  36. belong[x]=sum;
  37. vulue[sum]+=vul[x];
  38. for(;stack[top]!=x;top--) {
  39. belong[stack[top]]=sum;vis[stack[top]]=0;
  40. vulue[sum]+=vul[stack[top]];
  41. }
  42. vis[x]=0; top--;
  43. }
  44. }
  45. int rd[maxn];
  46. int q[maxn],vull[maxn];
  47. void top_sort(){
  48. int h=1,tail=0;
  49. for(int i=1;i<=sum;++i)
  50. if(rd[i]==0) vull[i]=vulue[i],q[++tail]=i;
  51. while(h<=tail) {
  52. int x=q[h++];
  53. for(int i=head1[x];i;i=edge1[i].next) {
  54. int v=edge1[i].v;
  55. if(rd[v]) {
  56. vull[v]=std::max(vull[v],vull[x]+vulue[v]);
  57. rd[v]--;
  58. if(rd[v]==0) q[++tail]=v;
  59. }
  60. }
  61. }
  62. int ans=0;
  63. for(int i=1;i<=sum;++i)
  64. ans=std::max(ans,vull[i]);
  65. printf("%d\n",ans);
  66. }
  67. int main() {
  68. scanf("%d%d",&n,&m);
  69. for(int i=1;i<=n;++i)
  70. scanf("%d",&vul[i]);
  71. for(int a,b,i=1;i<=m;++i) {
  72. scanf("%d%d",&a,&b);
  73. add_edge(a,b);
  74. }
  75. for(int i=1;i<=n;++i)
  76. if(!dfn[i])tarjan(i);
  77. for(int i=1;i<=n;++i)
  78. for(int j=head[i];j;j=edge[j].next) {
  79. int v=edge[j].v;
  80. if(belong[v]!=belong[i]) {
  81. add_edge1(belong[i],belong[v]);
  82. rd[belong[v]]++;
  83. }
  84. }
  85. top_sort();
  86. return 0;
  87. }

Tarjan缩点+DAG图dp的更多相关文章

  1. [SDOI2010] 所驼门王的宝藏 [建图+tarjan缩点+DAG dp]

    题面传送门: 传送门 思路: 看完题建模,容易得出是求单向图最长路径的问题 那么把这张图缩强联通分量,再在DAG上面DP即可 然而 这道题的建图实际上才是真正的考点 如果对于每一个点都直接连边到它所有 ...

  2. 洛谷 P2656 (缩点 + DAG图上DP)

    ### 洛谷 P2656 题目链接 ### 题目大意: 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖 ...

  3. 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 ...

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

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

  5. BZOJ1093 [ZJOI2007]最大半连通子图 【tarjan缩点 + DAG最长路计数】

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

  6. [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)

    题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...

  7. UVA 11324 The Largest Clique(强连通分量+缩点DAG的DP)

    题意:给定一个有向图,求出一个最大的结点集,这个节点集中的随意两个点之间至少一个能到达还有一个点. 思路:假设一个点在这个节点集中,那么它所在的强连通分量中的点一定所有在这个节点集中,反之亦然, 求出 ...

  8. 【Luogu】P3387缩点(Tarjan缩点+深搜DP)

    题没什么好说的,因为是模板题.求值我用的是dfs. 不能直接在原图上dfs,因为原图上有环的话会发生一些滑稽的事情.所以我们要用Tarjan缩点.因为此题点权全为正,所以如果在图上走一个环当然可以全走 ...

  9. poj2186Popular Cows+tarjan缩点+建图

    传送门: 题意: 给出m条关系,表示n个牛中的崇拜关系,这些关系满足传递性.问被所有牛崇拜的牛有几头: 思路: 先利用tarjan缩点,同一个点中的牛肯定就是等价的了,建立新的图,找出其中出度为0的点 ...

随机推荐

  1. leetcode-21-knapsack

    322. Coin Change Write a function to compute the fewest number of coins that you need to make up tha ...

  2. Linux中断体系结构

    1.中断处理体系结构 Linux内核将所有中断统一编号,使用一个irq_desc结构数组来描述这些中断. 数组声明在/linux/kernel/irq/handle.c中,其中#define NR_I ...

  3. LeetCode(290) Word Pattern

    题目 Given a pattern and a string str, find if str follows the same pattern. Here follow means a full ...

  4. hdu 6312

    Problem Description Alice and Bob are playing a game.The game is played on a set of positive integer ...

  5. poj 1742 多重背包问题 dp算法

    题意:硬币分别有 A1.....An种,每种各有C1......Cn个,问组成小于m的有多少种 思路:多重背包问题 dp[i][j]表示用前i种硬币组成j最多剩下多少个  dp=-1的表示凑不齐 dp ...

  6. java服务器备份(复制)

    public ResponseResult serverBackup (String[] datypeid)throws IOException{ ResponseResult rr = new Re ...

  7. 《Scrum实战》第3次课【富有成效的每日站会】作业汇总

    1组 崔儒: http://kecyru.blog.163.com/blog/static/2741661732017626101944123/ 2017-07-26 孟帅: http://www.c ...

  8. [Cake] 2. dotnet 全局工具 cake

    在上篇博客[Cake] 1. CI中的Cake中介绍了如何在CI中利用Cake来保持与CI/CD环境的解耦. 1. 简化cake的安装 当时dotnet 2.1还未正式发布,dotnet 还没有工具的 ...

  9. webdriver高级应用-js操作滚动条

    1.滑动页面的滚动条到页面最下面 2.滑动页面的滚动条到页面的某个元素 3.滑动页面的滚动条向下移动某个数量的像素 #encoding=utf-8 from selenium import webdr ...

  10. python学习-- 理解'*','*args','**','**kwargs'

    刚开始学习Python的时候,对有关args,kwargs,和*的使用感到很困惑.相信对此感到疑惑的人也有很多.我打算通过这个帖子来排解这个疑惑(希望能减少疑惑). 让我们通过以下5步来理解: 1.  ...