【JZOJ4771】【NOIP2016提高A组模拟9.9】爬山
题目描述
国家一级爬山运动员h10今天获得了一张有着密密麻麻标记的地图,在好奇心的驱使下,他又踏上了去爬山的路。
对于爬山,h10有一个原则,那就是不走回头路,于是他把地图上的所有边都标记成了有向边。他决定从点S出发,每到达一个新的节点他就可以获得一定的成就值。同时h10又是一个很珍惜时间的运动员,他不希望这次爬山的成就值白白浪费,所以最后他一定要在一个存档点停下,保存自己的成就值。
请你计算出在此次爬山运动中h10能够得到的最大成就值。保证h10能走到存档点。
输入
第一行两个整数 N,M,表示点数和边数。
接下来 M 行,每行两个整数 u,v,表示u到v有一条有向边(没有自环)。
第 M+2 行 N 个正整数,表示每个点的成就值。
接下来一行两个整数 S,p,表示出发点和存档点个数。
下面一行 p 个整数,表示存档点。
输出
一个正整数,表示最大成就值。
样例输入
5 7
5 1
3 1
2 5
3 5
4 3
4 2
4 5
7 6 3 2 2
4 3
1 5 2
样例输出
17
数据范围
对于 30% 的数据, N,M≤1000,并且地图为有向无环图。
对于 100% 的数据, N,M≤500000。(数据有梯度,注意答案的大小)
解法
这道题模型很明显,考虑图是一个DAG(有向无环图)的时候,拓扑排序上动态规划即可。
对于有环的情况,发现一个环的贡献是这个环上所有点的权值之和。
所以使用强连通分量把每个环都缩成一个点。
再使用拓扑排序上动态规划即可。
※手写栈需要
代码
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
#define ln(x,y) ll(log(x)/log(y))
#define sqr(x) ((x)*(x))
using namespace std;
const char* fin="aP2.in";
const char* fout="aP2.out";
const ll inf=0x7fffffff;
const ll maxn=500007,maxm=maxn*2;
ll n,m,i,j,k,st,En,tot,num;
ll a[maxn],fi[maxn],ne[maxm],la[maxm];
ll stack[maxn],dfn[maxn],low[maxn],fa[maxn];
ll ru[maxn];
ll b[maxn];
ll f[maxn],ans;
ll cz[maxn];
bool bz[maxn],en[maxn];
ll read(){
ll x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
void add_line(ll a,ll b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
struct handstack{
ll i,j,k,v;
}hs[maxn];
int hst=0;
void handdfs(ll v){
hs[++hst].v=v;
hs[hst].i=0;
while (hst){
if (hs[hst].i){
if (hs[hst].k){
if (!dfn[la[hs[hst].k]]) {
hs[hst+1].v=la[hs[hst].k];
hs[hst+1].i=0;
hst++;
continue;
}else if (bz[la[hs[hst].k]]) low[hs[hst].v]=min(low[la[hs[hst].k]],low[hs[hst].v]);
hs[hst].k=ne[hs[hst].k];
}else{
if (low[hs[hst].v]==dfn[hs[hst].v]){
while (stack[0]>hs[hst].j) {
for (hs[hst].k=fi[stack[stack[0]]];hs[hst].k;hs[hst].k=ne[hs[hst].k]) add_line(hs[hst].v,la[hs[hst].k]);
fa[stack[stack[0]]]=hs[hst].v;
a[fa[stack[stack[0]]]]+=a[stack[stack[0]]];
bz[stack[stack[0]--]]=false;
}
fa[stack[stack[0]]]=hs[hst].v;
bz[stack[stack[0]--]]=false;
}
hst--;
}
}else{
hs[hst].i=1;
dfn[hs[hst].v]=low[hs[hst].v]=++num;
bz[stack[hs[hst].j=++stack[0]]=hs[hst].v]=true;
hs[hst].k=fi[hs[hst].v];
}
}
}
void dfs(ll v){
ll i,j,k;
dfn[v]=low[v]=++num;
bz[stack[j=++stack[0]]=v]=true;
for (k=fi[v];k;k=ne[k])
if (!dfn[la[k]]) {
dfs(la[k]);
low[v]=min(low[la[k]],low[v]);
}else if (bz[la[k]]) low[v]=min(dfn[la[k]],low[v]);
if (low[v]==dfn[v]){
while (stack[0]>j) {
for (k=fi[stack[stack[0]]];k;k=ne[k]) add_line(v,la[k]);
fa[stack[stack[0]]]=v;
a[fa[stack[stack[0]]]]+=a[stack[stack[0]]];
bz[stack[stack[0]--]]=false;
}
fa[stack[stack[0]]]=v;
bz[stack[stack[0]--]]=false;
}
}
void topsort(){
ll i,j,k,head=0,tail=0;
for (i=1;i<=n;i++){
if (fa[i] && i==fa[i]) for (k=fi[i];k;k=ne[k]){
if (/*cz[fa[la[k]]]<i && */fa[la[k]]!=i) ru[fa[la[k]]]++/*,cz[fa[la[k]]]=i*/;
}
}
for (i=1;i<=n;i++) if (!ru[i] && fa[i]==i) {
b[++tail]=i;
f[i]=a[i];
break;
}
while (head++<tail){
if (en[b[head]]) ans=max(ans,f[b[head]]);
for (k=fi[b[head]];k;k=ne[k]) if (fa[la[k]]!=b[head]){
i=fa[la[k]];
f[i]=max(f[i],f[b[head]]+a[i]);
if (--ru[i]==0) b[++tail]=i;
}
}
}
int main(){
n=read();m=read();
for (i=1;i<=m;i++){
j=read();k=read();
add_line(j,k);
}
for (i=1;i<=n;i++) a[i]=read();
st=read();En=read();
handdfs(st);
for (i=1;i<=En;i++) j=read(),en[fa[j]]=true;
topsort();
printf("%lld",ans);
return 0;
}
【JZOJ4771】【NOIP2016提高A组模拟9.9】爬山的更多相关文章
- JZOJ 4732. 【NOIP2016提高A组模拟8.23】函数
4732. [NOIP2016提高A组模拟8.23]函数 (Standard IO) Time Limits: 1500 ms Memory Limits: 262144 KB Detailed ...
- 【NOIP2016提高A组模拟9.14】数列编辑器
题目 分析 比赛上,没有注意到询问只询问光标前面,于是只打了个暴力. 因为询问只询问光标前面,首先,当光标向后每移动到一个位置,顺便将这个位置的前缀和,和最大前缀和求出来. 总之,模拟 #includ ...
- 【NOIP2016提高A组模拟9.24】总结
第一题纯模拟,结果那个出题人脑子似乎进水了,空间限制开了1G!!! 导致我捉摸了半天为什么空间要开那么大,最后只能得出上面的结论. 第二题是个矩阵快速幂,比赛上我没把递推式求出来,但是根据各种乱搞,得 ...
- 【JZOJ4746】【NOIP2016提高A组模拟9.3】树塔狂想曲
题目描述 相信大家都在长训班学过树塔问题,题目很简单求最大化一个三角形数塔从上往下走的路径和.走的规则是:(i,j)号点只能走向(i+1,j)或者(i+1,j+1).如下图是一个数塔,映射到该数塔上行 ...
- 【JZOJ4745】【NOIP2016提高A组模拟9.3】看电影
题目描述 听说NOIP2016大家都考得不错,于是CCF奖励省常中了 K 张变形金刚5的电影票奖励OI队的同学去看电影.可是省常中OI队的同学们共有 N(N >= K)人.于是机智的你想到了一个 ...
- 【JZOJ4803】【NOIP2016提高A组模拟9.28】求导
题目描述 输入 输出 样例输入 2x^2+3x+1 样例输出 4x+3 数据范围 样例解释 求导的意思: 多项式是由若干个单项式构成的 单项式的一般形式是ax^b,其中ab都是常数,x是自变量 对于单 ...
- 【JZOJ4787】【NOIP2016提高A组模拟9.17】数格子
题目描述 输入 输出 样例输入 1 10000 3 10000 5 10000 0 0 样例输出 1 11 95 数据范围 每个测试点数据组数不超过10组 解法 状态压缩动态规划. 设f[i][j]表 ...
- [jzoj 4668] [NOIP2016提高A组模拟7.19] 腐败 解题报告(质数分类+慢速乘)
题目链接: http://172.16.0.132/senior/#main/show/4668 题目: 题解: 考虑把A数组里的每个元素分解质因数,对于每个质因数开一个vector存一下包含这个质因 ...
- [jzoj 4722] [NOIP2016提高A组模拟8.21] 跳楼机 解题报告 (spfa+同余)
题目链接: http://172.16.0.132/senior/#main/show/4722 题目: DJL为了避免成为一只咸鱼,来找srwudi学习压代码的技巧.Srwudi的家是一幢h层的摩天 ...
随机推荐
- HZOI20190828模拟32题解
题面:https://www.cnblogs.com/Juve/articles/11428730.html chinese: 考虑$\sum\limits_{i=0}^{n*m}i*f_i$的意义: ...
- CF 981C Useful Decomposition
题面 题目大意 给定一棵树,要求划分出几条链,使这几条链交于一点. 解题思路 因为所有链都要交于一点,所以必须交于一个度数最多的点.这样就形成了一个菊花形.然后从这个点出发到它的子树,判断子树的度数是 ...
- leetcode 696
696. Count Binary Substrings Input: "00110011" Output: 6 Explanation: There are 6 substrin ...
- 转:Linux fork与vfork的深入分析
源地址:http://linux.chinaitlab.com/c/831529.html 一)fork的概述 .操作系统对进程的管理,是通过进程表完成的.进程表中的每一个表项,记录的是当前操作系统中 ...
- js 打开app应用,如果没有安装就去下载
废话不多说,直接上代码 var APPCommon = { iphoneSchema: 'XingboTV://', iphoneDownUrl: 'https://itunes.apple.com/ ...
- MySQL抑制binlog日志中的BINLOG部分的方法
1.mysqlbinlog之base64-output参数 --base64-output=value This option determines when events should be dis ...
- 国内在Amazon fireTV或者fire平板下载应用(netflix\hulu\YouTube)的方法
1.首先需要vpn翻墙至U.S. 2.需要一个美国亚马逊账户,并设置收货地址 (Manage Your Fire & Kindle 1-Click Payment Settings ),如果只 ...
- 洛谷P3299 保护出题人
注意每一关的时候,前一关的植物会消失.保留整数指四舍五入. 解:冷静分析一波,列一个式子出来,发现每一关的植物攻击力要是(ai + ... + aj) / (xi + d * (i - j))的最大值 ...
- loj2544 「JXOI2018」游戏
https://loj.ac/problem/2544 自己太傻,一遇到有关数学的题就懵逼,这种简单题竟然还得靠NicoDafaGood 在$[l,r]$这个区间内,如果没有数是$x$的因数,我们称$ ...
- html5绘图工具选择
1. Chart.js 基于html5, 完全开源免费 功能过于简单,只有6种图,能满足小系统需求,使用简便,效果比较炫. http://www.bootcss.com/p/chart.js/ 2. ...