您的位置:首页 > 其它

BZOJ1179 [Apio2009]Atm

2016-09-20 15:32 316 查看

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的单向的道路到达其中的至少一个酒吧。

正解:tarjan+SPFA

解题报告:

  首先如果有环那么走进一个环上的点,显然把整个环都跑一遍会更优,也就是说一个强连通分量是完全一体的,所以可以直接缩环成点,然后跑最长路即可。

//It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
#define RG register
const int MAXN = 500011;
const int MOD = 500000;
int n,m,ecnt,belong[MAXN],cnt,ans;
int first[MAXN],next[MAXN],to[MAXN];
int quan[MAXN],s,p,dfn[MAXN],low[MAXN];
bool bar[MAXN],pd[MAXN],in[MAXN];
int stack[MAXN],top;
int head[MAXN],dis[MAXN],a[MAXN],l,tail,dui[MAXN];
struct edge{
int to,next;
}e[MAXN];
struct node{
int dis,x;
bool operator < (const node &a)const{
return a.dis>dis;
}
}tmp;
priority_queue<node>Q;

inline int getint()
{
RG int w=0,q=0; RG char c=getchar();
while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar();
while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
}

inline void tarjan(RG int x){
pd[x]=1; dfn[x]=low[x]=++ecnt; stack[++top]=x;
for(RG int i=first[x];i;i=next[i]) {
RG int v=to[i];
if(!dfn[v]) tarjan(v),low[x]=min(low[v],low[x]);
else if(pd[v]) low[x]=min(low[x],low[v]);
}
if(dfn[x]==low[x]) {
cnt++;
for(;;top--) {
belong[stack[top]]=cnt;
pd[stack[top]]=0;
if(stack[top]==x) { top--; break; }
}
}
}

inline void SPFA(){
dis[s]=a[s];
dui[++tail]=s;
while(l!=tail) {
l++; l%=MOD; RG int u=dui[l]; in[u]=0;
for(int i=head[u];i;i=e[i].next) {
RG int v=e[i].to;
if(dis[v]<dis[u]+a[v]) {
dis[v]=dis[u]+a[v];
if(!in[v]) {
in[v]=1;   dui[++tail]=v;
tail%=MOD;
}
}
}
}
for(RG int i=1;i<=cnt;i++) if(pd[i]) ans=max(ans,dis[i]);
printf("%d",ans);
}

inline void work(){
n=getint(); m=getint(); int x,y;
for(RG int i=1;i<=m;i++) {
x=getint(); y=getint();
next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
}
for(RG int i=1;i<=n;i++) quan[i]=getint();
s=getint(); p=getint(); for(RG int i=1;i<=p;i++) x=getint(),bar[x]=1;
ecnt=0; for(RG int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++) if(!belong[i]) belong[i]=++cnt;
ecnt=0; memset(pd,0,sizeof(pd));//判断环内是否有酒吧
s=belong[s];
for(RG int i=1;i<=n;i++) {
if(bar[i]) pd[belong[i]]=1;
a[belong[i]]+=quan[i];
for(RG int j=first[i];j;j=next[j]) {
if(belong[i]==belong[to[j]]) continue;
x=belong[i]; y=belong[to[j]];
e[++ecnt].next=head[x];  head[x]=ecnt; e[ecnt].to=y;
}
}
SPFA();
}

int main()
{
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: