题目链接:https://www.luogu.org/problemnew/show/P4742

题目大意:给一张有向图, 每个点都有点权,第一次经过该点时,该点的点权有贡献,求这张图上一条路径(终点随意)的贡献最大并且得到该路径上一个最大点权。

思路:

1.值得注意的是,这里并不是求最长路,也就是并不是求最多的点组成的路径,点可以少,但是必须点权和最大。

2.因为需要得到最大点权和以及最大点权,终点又不定,所以我们需要遍历图中每个点,来得到起点到该点的点权和以及路径上的最大点权。

3.先用tarjan进行缩点处理, 若不这样直接遍历原图非常耗时。缩点的‘点’中需要记录的信息是每个连通分量中点的权值和以及最大的点权。

4.还需要选择一个合理的遍历新图的方式, 那么选用 拓扑排序 ,(拓扑排序只有在设置汇点跳出的情况下得到的路径才不唯一,否则会根据点边关系遍历图中的每个点)

代码:

 #include<stdio.h>
#include<string.h>
#include<stack>
#include<queue>
#include<algorithm>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = ;
const int maxm = ;
typedef long long ll; int n, m, in[maxn];
int arr[maxn], max_node[maxn], sum_color[maxn];
int cnt, new_cnt, head[maxn], new_head[maxn];
int dfn[maxn], low[maxn], vis[maxn], belong[maxn], deep, color;
int dis[maxn], d_node[maxn];//dis代表从起点到该点的点权和,d_node代表起点到该点的点权最大值
stack<int>S;
queue<int>Q; struct Edge
{
int to, next;
}edge[maxm], new_edge[maxm]; void add(int a, int b)
{
edge[++ cnt].to = b;
edge[cnt].next = head[a];
head[a] = cnt;
} void new_add(int a, int b)
{
new_edge[++ new_cnt].to = b;
new_edge[new_cnt].next = new_head[a];
new_head[a] = new_cnt;
} void tarjan(int now)
{
dfn[now] = low[now] = ++ deep;
vis[now] = ;
S.push(now);
for(int i = head[now]; i != -; i = edge[i].next)
{
int to = edge[i].to;
if(!dfn[to])
{
tarjan(to);
low[now] = min(low[now], low[to]);
}
else if(vis[to])
low[now] = min(low[now], dfn[to]);
}
if(low[now] == dfn[now])
{
color ++;
while()
{
int temp = S.top();
S.pop();
vis[temp] = ;
belong[temp] = color;
max_node[color] = max(max_node[color], arr[temp]); //存每个强连通分量里亮度最大的点的值
sum_color[color] += arr[temp];//存每个强连通分量里的亮度和
if(temp == now)
break;
}
}
} void topu_sort()
{
// mem(dis, -inf);
while(!Q.empty())
Q.pop();
for(int i = ; i <= color; i ++)//topu_sort将入度为0的入队 ,并初始化d_node,每个分量的最大亮度
{
dis[i] = sum_color[i]; //初始化dis, d_node
d_node[i] = max_node[i];
if(!in[i])
Q.push(i);
}
while(!Q.empty())
{
int temp = Q.front();
Q.pop();
for(int i = new_head[temp]; i != -; i = new_edge[i].next)
{
int to = new_edge[i].to;
in[to] --;
if(!in[to])
Q.push(to);
if(dis[to] <= dis[temp] + sum_color[to])//选择新入的点,那么d_node就要与新入的缩点比较了
{
dis[to] = dis[temp] + sum_color[to];
d_node[to] = max(d_node[temp], max_node[to]);
}
/*
else if(dis[to] == dis[temp] + sum_color[to])
d_node[to] = max(d_node[temp], max_node[to]);
*/
}
}
int sum = -;
int maxx;
for(int i = ; i <= color; i ++)
{
if(dis[i] > sum)
{
sum = dis[i];
maxx = d_node[i];
}
}
printf("%d %d\n", sum, maxx);
} int main()
{
cnt = new_cnt = deep = color = ;
mem(head, -), mem(new_head, -), mem(in, );
mem(vis, ), mem(dfn, ), mem(low, );
mem(max_node, -inf), mem(sum_color, );
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i ++)
scanf("%d", &arr[i]); //存每个点的光亮值
for(int i = ; i <= m; i ++)
{
int a, b;
scanf("%d%d", &a, &b);
add(a, b);
}
for(int i = ; i <= n; i ++)
if(!dfn[i])
tarjan(i);
for(int i = ; i <= n; i ++)
{
for(int j = head[i]; j != -; j = edge[j].next)
{
int to = edge[j].to;
int x = belong[i], y = belong[to]; //将分量连边 缩点 注意是分量 belong
if(x != y)
{
new_add(x, y);
in[y] ++;
}
}
}
topu_sort();
return ;
}

2019/5/13 洛谷P4742 【tarjan缩点 + 拓扑dp】的更多相关文章

  1. UVA 11324.The Largest Clique tarjan缩点+拓扑dp

    题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相 ...

  2. 2019.01.04 洛谷P4719 【模板】动态dp(链分治+ddp)

    传送门 ddpddpddp模板题. 题意简述:给你一棵树,支持修改一个点,维护整棵树的最大带权独立集. 思路: 我们考虑如果没有修改怎么做. 貌似就是一个sbsbsb树形dpdpdp,fi,0f_{i ...

  3. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

  4. 洛谷 P3177 [HAOI2015]树上染色 树形DP

    洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...

  5. 洛谷 P4072 [SDOI2016]征途 斜率优化DP

    洛谷 P4072 [SDOI2016]征途 斜率优化DP 题目描述 \(Pine\) 开始了从 \(S\) 地到 \(T\) 地的征途. 从\(S\)地到\(T\)地的路可以划分成 \(n\) 段,相 ...

  6. NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序

    原文链接https://www.cnblogs.com/zhouzhendong/p/9258043.html 题目传送门 - 洛谷P3953 题目传送门 - Vijos P2030 题意 给定一个有 ...

  7. 【洛谷 P1073】 最优贸易 (Tarjan缩点+拓扑排序)

    题目链接 先\(Tarjan\)缩点,记录每个环内的最大值和最小值. 然后跑拓扑排序,\(Min[u]\)表示到\(u\)的最小值,\(ans[u]\)表示到\(u\)的答案,\(Min\)和\(an ...

  8. 洛谷P2515 [HAOI2010]软件安装(tarjan缩点+树形dp)

    传送门 我们可以把每一个$d$看做它的父亲,这样这个东西就构成了一个树形结构 问题是他有可能形成环,所以我们还需要一遍tarjan缩点 缩完点后从0向所有入度为零的点连边 然后再跑一下树形dp就行了 ...

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

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

随机推荐

  1. SQL Server孤立用戶

    如何解决孤立用户问题 http://blog.csdn.net/zzl1120/article/details/7394468 SQL SERVER孤立用户问题解决方法 http://www.2cto ...

  2. 收藏一个RMQ模板

    int a[1100]; int dp[maxn][20]; void rmq_init(){ for(int i=0;i<n;i++) dp[i][0]=a[i]; for(int j=1;( ...

  3. luogu P4194 矩阵

    嘟嘟嘟 先二分. 令二分的值为\(mid\),则对于每一行都要满足\(|\sum_{i = 1} ^ {n} (A_{ij} - B_{ij})|\),把绝对值去掉,就得到了\((\sum_{i = ...

  4. c语言if-else的效率比较

    闲着没事测试下if-else的执行效率 测试环境:Mac pro i7 2.3Ghz ...编译器gcc 4.9,代码没有进行优化-O0: 测试代码:c代码1: int main(){ int n=1 ...

  5. Java开发中使用事务

    一.      XML,使用tx标签配置拦截器实现事务 二.      Annotation方式 一.XML,使用tx标签配置拦截器实现事务 中主要配置中是tx:advice和aop:config两个 ...

  6. Linux之GDB调试命令

    gdb启动 gdb 程序名 l 查看源代码(默认显示十行) l 文件名:行数 l 文件名:函数名 添加断点 break + 行数 (b 也行) b 15 if i == 15 条件断点 i b 查看断 ...

  7. When you want to succeed as bad as you wanna breathe, then you’ll be successful.

    上周末登了次山,回来就各种矫情犯懒.今天周四一周又要完蛋,我发现自己真的是对时间流逝无可奈何.然后中午看了把小码哥网站还有MJ博客什么的,各种首期班大爆照,心中羞愧无比.年纪大也不能放弃自己啊,要不人 ...

  8. Zookeeper系列(十)zookeeper的服务端启动详述

    作者:leesf    掌控之中,才会成功:掌控之外,注定失败.出处:http://www.cnblogs.com/leesf456/p/6105276.html尊重原创,大家功能学习进步:  一.前 ...

  9. python之json读写

    #将字典转json并写入文件 import json i=3 j=5 a={'a':i,'b':j} js=json.dumps(a) print(js) with open("/Users ...

  10. Consider defining a bean of type `xxx` in your configuration问题解决

    在使用SpringBoot装配mybatis时出现了异常 *************************** APPLICATION FAILED TO START *************** ...