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

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

---------------------------------------------------------------------

#include<bits/stdc++.h>

#define rep(i, n) for(int i = 0; i < n; ++i)

#define clr(x, c) memset(x, c, sizeof(x))

#define foreach(i, x) for(__typeof(x.begin()) i = x.begin(); i != x.end(); i++)

using namespace std;

const int maxn = 500009;

struct edge {

int to;

edge* next;

} E[maxn], *pt = E, *head[maxn];

inline void addedge(int u, int v) {

pt->to = v, pt->next = head[u];

head[u] = pt++;

}

vector<int> G[maxn];

stack<int> S;

int dfn[maxn], low[maxn], scc[maxn], CK = 0, N = 0;

bool _bar[maxn], bar[maxn];

int _w[maxn], w[maxn], n, s, d[maxn];

void tarjan(int x) {

dfn[x] = low[x] = ++CK;

S.push(x);

foreach(it, G[x])

if(!dfn[*it]) {

tarjan(*it);

low[x] = min(low[x], low[*it]);

} else if(!~scc[*it])

low[x] = min(low[x], dfn[*it]);

if(low[x] == dfn[x]) {

N++;

for(int t = S.top(); ; t = S.top()) {

S.pop();

scc[t] = N;

w[N] += _w[t];

bar[N] |= _bar[t];

if(t == x) break;

}

}

}

void TARJAN() {

clr(w, 0), clr(dfn, 0), clr(low, 0), clr(scc, -1);

rep(i, n) if(!dfn[i]) tarjan(i);

}

void build() {

rep(i, n)

foreach(it, G[i]) if(scc[*it] != scc[i])

addedge(scc[i], scc[*it]);

s = scc[s];

}

struct node {

int x, d;

bool operator < (const node &o) const {

return d > o.d;

}

};

void dijkstra() {

rep(i, N) d[i] = 0;

priority_queue<node> Q;

d[s] = w[s];

Q.push( (node) {s, w[s]} );

while(!Q.empty()) {

node h = Q.top(); Q.pop();

int x = h.x, dist = h.d;

if(dist != d[x]) continue;

for(edge* e = head[x]; e; e = e->next) if(d[e->to] < d[x] + w[e->to]) {

d[e->to] = d[x] + w[e->to];

Q.push( (node) {e->to, d[e->to]} );

}

}

int ans = 0;

rep(i, N) if(bar[i])

ans = max(ans, d[i]);

printf("%d\n", ans);

}

void Read() {

int m;

cin >> n >> m;

while(m--) {

int u, v;

scanf("%d%d", &u, &v); u--; v--;

G[u].push_back(v);

}

rep(i, n) scanf("%d", _w + i);

scanf("%d%d", &s, &m); s--;

clr(_bar, 0);

while(m--) {

int t;

scanf("%d", &t); t--;

_bar[t] = true;

}

}

int main() {

freopen("test.in", "r", stdin);

Read();

TARJAN();

build();

dijkstra();

return 0;

}

---------------------------------------------------------------------

1179: [Apio2009]Atm

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 1919  Solved: 762
[Submit][Status][Discuss]

Description

Input

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号

Output

输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。

Sample Input

6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1 5
1 4
4
3
5
6

Sample Output

47

HINT

50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

Source

时间: 2024-10-12 09:59:42

BZOJ 1179: [Apio2009]Atm( tarjan + 最短路 )的相关文章

bzoj 1179[Apio2009]Atm (tarjan+spfa)

题目 输入 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 输出 输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数. 样例输入 6 7 1

bzoj 1179: [Apio2009]Atm【tarjan+spfa】

明明优化了spfa还是好慢-- 因为只能取一次值,所以先tarjan缩点,把一个scc的点权和加起来作为新点的点权,然后建立新图.在新图上跑spfa最长路,最后把酒吧点的dis取个max就是答案. #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int N=500005,inf=1e9; int n,m,h[N],

bzoj 1179: [Apio2009]Atm

Description Input 第 一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路 的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就 是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的

缩点+spfa最长路【bzoj】 1179: [Apio2009]Atm

[bzoj] 1179: [Apio2009]Atm Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧.Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫.他将从市中心 出发,沿着单向道路行驶,抢劫所有他 途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利.使用高超

1179: [Apio2009]Atm

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1629  Solved: 615[Submit][Status] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S

【BZOJ】1179: [Apio2009]Atm(tarjan+spfa)

http://www.lydsy.com/JudgeOnline/problem.php?id=1179 缩点建图... #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> #include <set> #

tarjan+spfa最短路 BZOJ1179 [Apio2009] Atm

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 3641  Solved: 1552[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下

【BZOJ-1179】Atm Tarjan + SPFA

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2407  Solved: 993[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来

bzoj1179: [Apio2009]Atm

tarjan缩点就是DAG上求最长路把...然而我并不会求...只会写spfa了... #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<stack> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #defin