题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1179

题解:

  一道比较综合的图论题
  直接讲正解:
  如果这个图G中存在某个强连通分量,那么这个强连通分量中的所有ATM即可视为都被抢到,所有的酒吧都可视为重点,并且也可以从这个强连通分量的任何结点出发继续向外扩展
  所以先做一遍Tarjan,找出强连通分量,然后重新构图,把每个强连通分量缩成一个点,此点的权值即为原先强连通分量里所有点权之和,判断此点中有没有酒吧,再将原先所有连接强连通分量的边连接在这个点
  最后做SPFA,找出权值最大的路径
  这道题时间限制15s,空间162MB,所以一般不会TLE或MLE
 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 500010
#define MAXM 500010
int n,m,time,cnt,head1[MAXN],DFN[MAXN],Low[MAXN],stack[MAXN],top,a1[MAXN],belong[MAXN];
bool vis[MAXN],bar1[MAXN];
struct node1
{
int v,next;
}edge1[MAXM];
//以上变量基本是在进行tarjan(及之前)使用
int heads[MAXN],mm,a2[MAXN],s,p,d[MAXN],q[MAXN],head,tail,ans;
bool viss[MAXN];
struct node2
{
int v,next;
}edge2[MAXM];
//以上变量是在进行SPFA时使用
//a存放点权,bar记录是否有酒吧
bool bar2[MAXN];
void add(int x,int y)
{
edge1[++cnt].next=head1[x];
head1[x]=cnt;
edge1[cnt].v=y;
}
void buildmap(int k)//重新建图、连边
{
for(int i=;i<=n;i++)
{
if(belong[i]==k)
{
for(int j=head1[i];j;j=edge1[j].next)
{
if(belong[edge1[j].v]==k)continue;
edge2[++m].next=heads[k];
heads[k]=m;
edge2[m].v=belong[edge1[j].v];
}
}
}
}
void tarjan(int u)
{
DFN[u]=Low[u]=++time;
vis[u]=true;
stack[++top]=u;
for(int i=head1[u];i;i=edge1[i].next)
{
int v=edge1[i].v;
if(!DFN[v])
{
tarjan(v);
Low[u]=min(Low[u],Low[v]);
}
else if(vis[v])Low[u]=min(Low[u],DFN[v]);
}
if(DFN[u]==Low[u])
{
int i;
cnt++;
do
{
i=stack[top--];
vis[i]=false;
belong[i]=cnt;
a2[cnt]+=a1[i];
if(bar1[i])bar2[cnt]=true;//先更新点权和是否有酒吧
}while(u!=i);
}
}
void SPFA()
{
head=;tail=;
q[]=s;
viss[s]=;
while(head<tail)
{
for(int i=heads[q[head]];i!=;i=edge2[i].next)
{
if(d[q[head]]+a2[edge2[i].v]>d[edge2[i].v])//注意,这里不是边权,是点权
{
d[edge2[i].v]=d[q[head]]+a2[edge2[i].v];
if(!viss[edge2[i].v])
{
q[tail++]=edge2[i].v;
viss[edge2[i].v]=true;
}
}
}
viss[q[head]]=false;
head++;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=;i<=n;i++)
{
scanf("%d",&a1[i]);
}
scanf("%d%d",&s,&p);
for(int i=;i<=p;i++)
{
int x;
scanf("%d",&x);
bar1[x]=true;
}
cnt=;
m=;
for(int i=;i<=n;i++)
if(!DFN[i])tarjan(i);
for(int i=;i<=cnt;i++)
buildmap(i);
s=belong[s];
for(int i=;i<=cnt;i++)
{
d[i]=a2[i];
}
SPFA();
for(int i=;i<=cnt;i++)
{
if(bar2[i])ans=max(ans,d[i]);
}
printf("%d",ans);
return ;
}

bzoj 1179 Atm的更多相关文章

  1. BZOJ 1179 Atm 题解

    BZOJ 1179 Atm 题解 SPFA Algorithm Tarjan Algorithm Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来 ...

  2. BZOJ 1179 Atm(强连通分量缩点+DP)

    题目说可以通过一条边多次,且点权是非负的,所以如果走到图中的一个强连通分量,那么一定可以拿完这个强连通分量上的money. 所以缩点已经很明显了.缩完点之后图就是一个DAG,对于DAG可以用DP来求出 ...

  3. bzoj 1179 [APIO 2009]Atm(APIO水题) - Tarjan - spfa

    Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一 ...

  4. BZOJ 1179: [Apio2009]Atm( tarjan + 最短路 )

    对于一个强连通分量, 一定是整个走或者不走, 所以tarjan缩点然后跑dijkstra. ------------------------------------------------------ ...

  5. bzoj 1179[Apio2009]Atm (tarjan+spfa)

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

  6. BZOJ 1179 [Apio2009]Atm(强连通分量)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1179 [题目大意] 给出一张有向带环点权图,给出一些终点,在路径中同一个点的点权只能累 ...

  7. bzoj 1179: [Apio2009]Atm

    Description Input 第 一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路 的起点和终点的 ...

  8. bzoj 1179 [Apio2009]Atm 缩点+最短路

    [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 4290  Solved: 1893[Submit][Status][Dis ...

  9. BZOJ 1179 抢掠计划atm (缩点+有向无环图DP)

    手动博客搬家: 本文发表于20170716 10:58:18, 原地址https://blog.csdn.net/suncongbo/article/details/81061601 https:// ...

随机推荐

  1. 转:浅谈Spectral Clustering 谱聚类

    浅谈Spectral Clustering Spectral Clustering,中文通常称为“谱聚类”.由于使用的矩阵的细微差别,谱聚类实际上可以说是一“类”算法. Spectral Cluste ...

  2. C++中Set的使用

    /* #include <string> // 使用 string 类时须包含这个文件 #include <iostream> // 这个就加上去吧.c++的输入和输出. us ...

  3. Educational Codeforces Round 40 F. Runner's Problem

    Educational Codeforces Round 40 F. Runner's Problem 题意: 给一个$ 3 * m \(的矩阵,问从\)(2,1)$ 出发 走到 \((2,m)\) ...

  4. CF916E Jamie and Tree 解题报告

    CF916E Jamie and Tree 题意翻译 有一棵\(n\)个节点的有根树,标号为\(1-n\),你需要维护一下三种操作 1.给定一个点\(v\),将整颗树的根变为\(v\) 2.给定两个点 ...

  5. B树,B+树,B*树简介

    B树(有些人也叫B-树) 是一种多路搜索树 : 1.定义任意非叶子结点最多只有M个儿子:且M>2: 2.根结点的儿子数为[2, M]: 3.除根结点以外的非叶子结点的儿子数为[M/2, M]: ...

  6. React组件通信

    1.父子通信 父 -> 子 props子 -> 父 回调函数,父组件通过props向子组件传递一个函数,子组件调用函数,父组件在回调函数中用setState改变自身状态 2.跨层级通信 1 ...

  7. 【数位DP】【SCOI2009】windy数

    传送门 Description \(windy\)定义了一种\(windy\)数.不含前导零且相邻两个数字之差至少为\(2\)的正整数被称为\(windy\)数.\(windy\)想知道, 在\(A\ ...

  8. 【单调队列】【P1776】宝物筛选

    传送门 Description 终于,破解了千年的难题.小FF找到了王室的宝物室,里面堆满了无数价值连城的宝物--这下小FF可发财了,嘎嘎.但是这里的宝物实在是太多了,小FF的采集车似乎装不下那么多宝 ...

  9. MyBatis子查询

    一.父查询BaseChildResultMap: <?xml version="1.0" encoding="UTF-8" ?> <!DOCT ...

  10. Nginx的启动、停止、平滑重启

    转载自:http://www.xj123.info/2572.html 启动Nginx /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/ngi ...