这题一看就是缩点,但是缩完点怎么办呢?首先我们把所有的包含酒吧的缩点找出来,打上标记,然后建立一张新图,

每个缩点上的点权就是他所包含的所有点的点权和。但是建图的时候要注意,每一对缩点之间可能有多条边,所以我们可以先把重边去除一下,在建立新图,具体操作如下:

 for(int i=;i<=n;i++)
{
if(vis[i]==) continue;
for(int j=last[i];j;j=g[j].next)
{
int v=g[j].to;
if(g[i].co!=g[v].co&&vis[v]==)
{
e[++cnt].a=g[i].co;
e[cnt].b=g[v].co;
}
}
}
sort(e+,e+cnt+,cmp);
for(int i=;i<=cnt;i++)
{
if(e[i].a!=e[i-].a||e[i].b!=e[i-].b)
{
add1(e[i].a,e[i].b);
}
}

具体思路就是先枚举所有点和所有边,如果两个点不属于同一个强联通分量,那么就用e来把边存一下,然后对e进行排序

,去重,再建图。

建完图之后就好办了,可以跑spfa单源最长路,也可以dp,因为最后一定会终止在酒吧,所以就取所有打过标记的节点的最大值就好了。

最后附上代码:

 #include<iostream>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define maxn 500005
using namespace std;
struct edge
{
int next;
int to;
int co;
}g[maxn]; struct edge1
{
int next;
int to;
}g1[maxn];
struct edhe
{
int a,b;
}e[maxn]; inline int read()
{
char c=getchar();
int res=,x=;
while(c<''||c>'')
{
if(c=='-')
x=-;
c=getchar();
}
while(c>=''&&c<='')
{
res=res*+(c-'');
c=getchar();
}
return x*res;
} int n,m,aa,bb,num,s,p,tot,top,col,num1,ans,ae,cnt;
int last[maxn],a[maxn],b[maxn],dfn[maxn],st[maxn],low[maxn];
int shu[maxn],d[maxn],last1[maxn],sum[maxn],vis[maxn]; inline void add(int from,int to)
{
g[++num].next=last[from];
g[num].to=to;
last[from]=num;
} inline void add1(int from,int to)
{
g1[++num1].next=last1[from];
g1[num1].to=to;
last1[from]=num1;
} inline void tarjan(int u)
{
low[u]=dfn[u]=++tot;
st[++top]=u;
for(int i=last[u];i;i=g[i].next)
{
int v=g[i].to;
if(!dfn[v])
{
tarjan(v);
if(low[v]<low[u])
low[u]=low[v];
}
else if(!g[v].co)
{
if(dfn[v]<low[u])
low[u]=dfn[v];
}
}
if(low[u]==dfn[u])
{
g[u].co=++col;
while(st[top]!=u)
{
g[st[top]].co=col;
top--;
}
top--;
}
} void dfs(int x)
{
for(int i=last1[x];i;i=g1[i].next)
{
int v=g1[i].to;
if(sum[x]+shu[v]>sum[v])
{
sum[v]=sum[x]+shu[v];
dfs(v);
}
}
} bool cmp(edhe a,edhe b)
{
if(a.a==b.a)
{
return a.b<b.b;
}
else return a.a<b.a;
} int main()
{
n=read();
m=read();
for(int i=;i<=m;i++)
{
aa=read();bb=read();
add(aa,bb);
}
for(int i=;i<=n;i++)
{
a[i]=read();
}
s=read();p=read();
for(int i=;i<=p;i++)
{
aa=read();
b[aa]=;
}
for(int i=;i<=n;i++)
{
if(!dfn[i])
tarjan(i);
}
for(int i=;i<=n;i++)
{
shu[g[i].co]+=a[i];
if(b[i]==)
{
d[g[i].co]=;
}
}
for(int i=;i<=n;i++)
{
if(vis[i]==) continue;
for(int j=last[i];j;j=g[j].next)
{
int v=g[j].to;
if(g[i].co!=g[v].co)
{
e[++cnt].a=g[i].co;
e[cnt].b=g[v].co;
}
}
}
sort(e+,e+cnt+,cmp);
for(int i=;i<=cnt;i++)
{
if(e[i].a!=e[i-].a||e[i].b!=e[i-].b)
{
add1(e[i].a,e[i].b);
}
}
sum[g[s].co]=shu[g[s].co];
dfs(g[s].co);
for(int i=;i<=col;i++)
{
if(d[i]==)
{
if(ans<sum[i])
ans=sum[i];
}
}
printf("%d",ans);
return ;
}

洛谷 P3627 [APIO2009]抢掠计划的更多相关文章

  1. 【题解】洛谷P3627 [APIO2009]抢掠计划(缩点+SPFA)

    洛谷P3627:https://www.luogu.org/problemnew/show/P3627 思路 由于有强连通分量 所以我们可以想到先把整个图缩点 缩点完之后再建一次图 把点权改为边权 并 ...

  2. 洛谷 P3627 [APIO2009]抢掠计划 Tarjan缩点+Spfa求最长路

    题目地址:https://www.luogu.com.cn/problem/P3627 第一次寒假训练的结测题,思路本身不难,但对于我这个码力蒟蒻来说实现难度不小-考试时肛了将近两个半小时才刚肛出来. ...

  3. [洛谷P3627][APIO2009]抢掠计划

    题目大意:给你一张$n(n\leqslant5\times10^5)$个点$m(m\leqslant5\times10^5)$条边的有向图,有点权,给你起点和一些可能的终点.问从起点开始,到任意一个终 ...

  4. 洛谷 P3627 [APIO2009]抢掠计划 题解

    Analysis 建图+强连通分量+SPFA求最长路 但要保证最后到达的点中包含酒馆 虽然思路并不难想,但要求的代码能力很高. #include<iostream> #include< ...

  5. 洛谷 P3627 【抢掠计划】

    题库:洛谷 题号:3627 题目:抢掠计划 link:https://www.luogu.org/problem/P3627 思路 : 这道题是一道Tarjan + 最长路的题.首先,我们用Tarja ...

  6. BZOJ1179或洛谷3672 [APIO2009]抢掠计划

    BZOJ原题链接 洛谷原题链接 在一个强连通分量里的\(ATM\)机显然都可被抢,所以先用\(tarjan\)找强连通分量并缩点,在缩点的后的\(DAG\)上跑最长路,然后扫一遍酒吧记录答案即可. # ...

  7. 洛谷3627 [APIO2009]抢掠计划

    题目描述 输入格式: 第一行包含两个整数 N.M.N 表示路口的个数,M 表示道路条数.接下来 M 行,每行两个整数,这两个整数都在 1 到 N 之间,第 i+1 行的两个整数表示第 i 条道路的起点 ...

  8. P3627 [APIO2009]抢掠计划

    P3627 [APIO2009]抢掠计划 Tarjan缩点+最短(最长)路 显然的缩点...... 在缩点时,顺便维护每个强连通分量的总权值 缩完点按照惯例建个新图 然后跑一遍spfa最长路,枚举每个 ...

  9. 洛谷 P3627 [APIO2009](抢掠计划 缩点+spfa)

    题目描述 Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri 的酒吧也都设 ...

随机推荐

  1. Python使用的技巧

    1. 给你一个字符串 a, 请你输出逆序之后的a. 例如:a=‘xydz’ 则输出:zdyx a=a[::-1] print(a) 扩展:Python切片操作. 2. 给你两个正整数a和b, 输出它们 ...

  2. MySql数据库学习笔记(2)

    DELETE 语法:delete from 表名 [where condition] delete from grade; TRUNCATE 用于完全清空表数据,但表结构.索引.约束不变: 语法: t ...

  3. Java开发环境配置(2)--jdk配置和 多个JDK问题处理

    ==2018-8-15 16:41:06 更新 服务器 jdk1.6升级为1.8,没有卸载原来的1.6,直接安装1.8. 更改环境变量的 JAVA_HOME所指路径后, cmd 输入 java -ve ...

  4. Centos7配置静态IP后无法ping通外部网络的问题(无法上网)

    打开ifcfg-ens33配置文件,注意下面标记部分 建议: (1)ifcfg-ens33 DNS 配置 DNS1=8.8.8.8 DNS2=8.8.4.4 (2)配置DNS解析才能够识别外部的IP域 ...

  5. centos系统下安装python3以及pip3

    首先查看一下系统当前的python版本 python -V 1.安装必要工具 yum-utils 它的功能是管理repository及扩展包的工具yum install yum-utils -y 2. ...

  6. SpringSecurity如何退出登录

    ⒈如何退出登录? SpringSecurity默认为我们提供了退出操作,我们只需要访问特定的url就可以退出登录了 <!DOCTYPE html> <html lang=" ...

  7. eMMC基础技术9:分区管理

    [转]http://www.wowotech.net/basic_tech/emmc_partitions.html 0.前言 eMMC 标准中,将内部的 Flash Memory 划分为 4 类区域 ...

  8. vue后台项目记录

    1.当我们用axios进行接口访问时,必须同时使用Qs,否则后端接收不到所传的数据! npm 安装qs,然后引用 import Qs from 'qs' // 创建axios实例 const serv ...

  9. Python 脚本碎片

    基本输入输出 用户名/密码 #!/usr/bin/env python3 # -*- coding:utf-8 -*- # Liu Lei import getpass username = inpu ...

  10. BZOJ3224/LOJ104 普通平衡树 pb_ds库自带红黑树

    您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x2. 删除x(若有多个相同的数,因只删除一个)3. 查询x的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. ...