题目描述

国家一级爬山运动员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】爬山的更多相关文章

  1. JZOJ 4732. 【NOIP2016提高A组模拟8.23】函数

    4732. [NOIP2016提高A组模拟8.23]函数 (Standard IO) Time Limits: 1500 ms  Memory Limits: 262144 KB  Detailed ...

  2. 【NOIP2016提高A组模拟9.14】数列编辑器

    题目 分析 比赛上,没有注意到询问只询问光标前面,于是只打了个暴力. 因为询问只询问光标前面,首先,当光标向后每移动到一个位置,顺便将这个位置的前缀和,和最大前缀和求出来. 总之,模拟 #includ ...

  3. 【NOIP2016提高A组模拟9.24】总结

    第一题纯模拟,结果那个出题人脑子似乎进水了,空间限制开了1G!!! 导致我捉摸了半天为什么空间要开那么大,最后只能得出上面的结论. 第二题是个矩阵快速幂,比赛上我没把递推式求出来,但是根据各种乱搞,得 ...

  4. 【JZOJ4746】【NOIP2016提高A组模拟9.3】树塔狂想曲

    题目描述 相信大家都在长训班学过树塔问题,题目很简单求最大化一个三角形数塔从上往下走的路径和.走的规则是:(i,j)号点只能走向(i+1,j)或者(i+1,j+1).如下图是一个数塔,映射到该数塔上行 ...

  5. 【JZOJ4745】【NOIP2016提高A组模拟9.3】看电影

    题目描述 听说NOIP2016大家都考得不错,于是CCF奖励省常中了 K 张变形金刚5的电影票奖励OI队的同学去看电影.可是省常中OI队的同学们共有 N(N >= K)人.于是机智的你想到了一个 ...

  6. 【JZOJ4803】【NOIP2016提高A组模拟9.28】求导

    题目描述 输入 输出 样例输入 2x^2+3x+1 样例输出 4x+3 数据范围 样例解释 求导的意思: 多项式是由若干个单项式构成的 单项式的一般形式是ax^b,其中ab都是常数,x是自变量 对于单 ...

  7. 【JZOJ4787】【NOIP2016提高A组模拟9.17】数格子

    题目描述 输入 输出 样例输入 1 10000 3 10000 5 10000 0 0 样例输出 1 11 95 数据范围 每个测试点数据组数不超过10组 解法 状态压缩动态规划. 设f[i][j]表 ...

  8. [jzoj 4668] [NOIP2016提高A组模拟7.19] 腐败 解题报告(质数分类+慢速乘)

    题目链接: http://172.16.0.132/senior/#main/show/4668 题目: 题解: 考虑把A数组里的每个元素分解质因数,对于每个质因数开一个vector存一下包含这个质因 ...

  9. [jzoj 4722] [NOIP2016提高A组模拟8.21] 跳楼机 解题报告 (spfa+同余)

    题目链接: http://172.16.0.132/senior/#main/show/4722 题目: DJL为了避免成为一只咸鱼,来找srwudi学习压代码的技巧.Srwudi的家是一幢h层的摩天 ...

随机推荐

  1. vue.js_02_vue.js的基础指令

    1.v-cloak 作用:解决插值表达式闪烁的问题 当网速过慢时,或者加载数据时间过长时,网页会出现  {{msg}}  的现象 使用方法: <!--缺陷需要写style样式--> < ...

  2. Ajax技术 - (Asynchronous JavaScript + XML)

    Ajax Ajax = 异步JavaScript和XML,Ajax是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,Ajax可以使网页实现异步更新.可以再网页不重新加载的情况下, ...

  3. 构建支持中文字体的moviepy镜像

    首先是系统的环境问题. linux 安装 moviepy需要很多依赖,安装起来费神费力.配置起来也非常麻烦,最简单的办法是直接使用他人构建好的镜像文件. 再就是字体显示问题. 镜像中的imagmagi ...

  4. linux下用eclipse开发mapreduce遇到的问题

    Unable to create the selected preference page.org/apache/hadoop/eclipse/preferences/MapReducePrefere ...

  5. idea创建管理项目

    创建分支时以master为准,这时master上的代码已合并完毕,idea右下角可以看到本地和远程的分支,在本地合并时,先切换到master上,选中要合并到master的分支,选择merge into ...

  6. Linux 拷贝有更改的文件

    cp -Ruv /home/username/trunk_new/app/* /data/httpdocs/wwwroot/app/

  7. 玩转webpack之webpack的entry output

    webpack的入口配置项表示要配置的文件就是开发环境或者生产环境 浏览器本身不能认识的一些东西必须经过webpack的编译才能认识,但是要去写的时候我们经常用到预编译什么的比如scss比如jsx甚至 ...

  8. IO流6 --- FileReader中使用read(char[] cbuf)读入数据 --- 技术搬运工(尚硅谷)

    FileReader 字符输入流 @Test public void test2(){ File file = new File("hello.txt"); FileReader ...

  9. 使用Pycharm写一个网络爬虫

    在初步了解网络爬虫之后,我们接下来就要动手运用Python来爬取网页了. 我们知道,网络爬虫应用一般分为两个步骤: 1.通过网页链接获取内容: 2.对获得的网页内容进行处理 这两个步骤需要分别使用不同 ...

  10. day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    一级缓存的更新会自动同步到二级缓存. @SuppressWarnings("all") @Test // 将内存中的数据写到硬盘 public void demo7(){ Sess ...