BZOJ1179 [Apio2009]Atm

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

解题报告:

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

 

  1 //It is made by jump~
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <ctime>
  9 #include <vector>
 10 #include <queue>
 11 #include <map>
 12 #include <set>
 13 using namespace std;
 14 typedef long long LL;
 15 #define RG register
 16 const int MAXN = 500011;
 17 const int MOD = 500000;
 18 int n,m,ecnt,belong[MAXN],cnt,ans;
 19 int first[MAXN],next[MAXN],to[MAXN];
 20 int quan[MAXN],s,p,dfn[MAXN],low[MAXN];
 21 bool bar[MAXN],pd[MAXN],in[MAXN];
 22 int stack[MAXN],top;
 23 int head[MAXN],dis[MAXN],a[MAXN],l,tail,dui[MAXN];
 24 struct edge{
 25     int to,next;
 26 }e[MAXN];
 27 struct node{
 28     int dis,x;
 29     bool operator < (const node &a)const{
 30     return a.dis>dis;
 31     }
 32 }tmp;
 33 priority_queue<node>Q;
 34 
 35 inline int getint()
 36 {
 37        RG int w=0,q=0; RG char c=getchar();
 38        while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
 39        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
 40 }
 41 
 42 inline void tarjan(RG int x){
 43     pd[x]=1; dfn[x]=low[x]=++ecnt; stack[++top]=x;
 44     for(RG int i=first[x];i;i=next[i]) {
 45     RG int v=to[i]; 
 46     if(!dfn[v]) tarjan(v),low[x]=min(low[v],low[x]);
 47     else if(pd[v]) low[x]=min(low[x],low[v]);
 48     }
 49     if(dfn[x]==low[x]) {
 50     cnt++;
 51     for(;;top--) {
 52         belong[stack[top]]=cnt;
 53         pd[stack[top]]=0;
 54         if(stack[top]==x) { top--; break; }
 55     }
 56     }
 57 }
 58 
 59 inline void SPFA(){
 60     dis[s]=a[s];
 61     dui[++tail]=s;
 62     while(l!=tail) {
 63     l++; l%=MOD; RG int u=dui[l]; in[u]=0;
 64     for(int i=head[u];i;i=e[i].next) {
 65         RG int v=e[i].to; 
 66         if(dis[v]<dis[u]+a[v]) {
 67         dis[v]=dis[u]+a[v];
 68         if(!in[v]) {
 69             in[v]=1;   dui[++tail]=v; 
 70             tail%=MOD;
 71         }
 72         }
 73     }
 74     }
 75     for(RG int i=1;i<=cnt;i++) if(pd[i]) ans=max(ans,dis[i]);
 76     printf("%d",ans);
 77 }
 78 
 79 inline void work(){
 80     n=getint(); m=getint(); int x,y;
 81     for(RG int i=1;i<=m;i++) {
 82     x=getint(); y=getint();
 83     next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;    
 84     }
 85     for(RG int i=1;i<=n;i++) quan[i]=getint();
 86     s=getint(); p=getint(); for(RG int i=1;i<=p;i++) x=getint(),bar[x]=1;
 87     ecnt=0; for(RG int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
 88     for(int i=1;i<=n;i++) if(!belong[i]) belong[i]=++cnt;
 89     ecnt=0; memset(pd,0,sizeof(pd));//判断环内是否有酒吧
 90     s=belong[s];
 91     for(RG int i=1;i<=n;i++) {
 92     if(bar[i]) pd[belong[i]]=1;
 93     a[belong[i]]+=quan[i];
 94     for(RG int j=first[i];j;j=next[j]) {
 95         if(belong[i]==belong[to[j]]) continue;
 96         x=belong[i]; y=belong[to[j]];
 97          e[++ecnt].next=head[x];  head[x]=ecnt; e[ecnt].to=y;
 98     }
 99     }
100     SPFA();
101 }
102 
103 int main()
104 {
105   work();
106   return 0;
107 }

 

posted @ 2016-09-20 15:32  ljh_2000  阅读(297)  评论(0编辑  收藏  举报