题目链接: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. vim 插件安装

    一.pathogen简介 通常情况下安装vim插件,通常是将所有的插件和相关的doc文件都安装在中一文件夹中,如将插件全部安装在/usr/share/vim/vim73/plugin/目录下,将帮助文 ...

  2. [Luogu] Mayan游戏

    https://www.luogu.org/problemnew/show/P1312 太恶心了 #include <cstdio> #include <algorithm> ...

  3. 【线性代数】4-3:最小二乘近似(Least Squares Approximations)

    title: [线性代数]4-3:最小二乘近似(Least Squares Approximations) categories: Mathematic Linear Algebra keywords ...

  4. codeforces#1187E. Tree Painting(树换根)

    题目链接: http://codeforces.com/contest/1187/problem/E 题意: 给出一颗树,找到一个根节点,使所有节点的子节点数之和最大 数据范围: $2 \le n \ ...

  5. mysql delete别名

    有一个表的数据比较大,然后需要进行关联删除,删除的时候发现如下SQL报错:ELETE FROM test.test1 a WHERE EXISTS (SELECT 1 FROM test.test2 ...

  6. Go语言编程中字符串切割方法小结

    1.func Fields(s string) []string,这个函数的作用是按照1:n个空格来分割字符串最后返回的是[]string的切片 复制代码代码如下: import ( "fm ...

  7. MAC ADDRESS

    可以使用手机Wifi或蓝牙的MAC地址作为设备标识,但是并不推荐这么做,原因有以下两点:硬件限制:并不是所有的设备都有Wifi和蓝牙硬件,硬件不存在自然也就得不到这一信息.获取的限制:如果Wifi没有 ...

  8. 尚硅谷周阳老师-redis脑图课件

    因为脑图原件是.mmap格式,使用wps和xmind打开都会有格式不兼容的问题,这里我们可以使用mindmanager存为html5交互式格式, 提供在线阅读.因为阿里云学生服务器带宽有限,这里打开加 ...

  9. python操作Elasticsearch (一、例子)

    E lasticsearch是一款分布式搜索引擎,支持在大数据环境中进行实时数据分析.它基于Apache Lucene文本搜索引擎,内部功能通过ReST API暴露给外部.除了通过HTTP直接访问El ...

  10. 数据结构之链表(Linked list)

    1, 无序链表(Unordered linked list) 链表是有若干个数据节点依次链接成的数据结构,如下图所示,每一个数据节点包括包括数据和一个指向下一节点的指针.(python中的list就是 ...