bzoj1179: [Apio2009]Atm

很久没更博客了qwq

https://www.lydsy.com/JudgeOnline/problem.php?id=1179

似乎不是很难,点可以重复走,但只算一次,这么办?考虑把点缩起来,显然这样就可以解决了。

之后跑跑spfa就行了

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 using namespace std;
 5 const int N=500000+5;
 6 int v[N],nxt[N],first[N],cnt;
 7 int bl[N],b[N],w[N];
 8 int low[N],dfn[N],tim;
 9 int st[N],top,sz;
10 int bar[N],s,n,m,p;
11 int aa[N],bb[N];
12 bool vis[N];
13 
14 void read(int &x){
15     x=0;int f=1;char c=getchar();
16     while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
17     while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c-'0');c=getchar();}
18     x*=f;
19 }
20 
21 void add(int a,int b){
22     v[++cnt]=b;
23     nxt[cnt]=first[a];
24     first[a]=cnt;
25 }
26 
27 void tarjan(int x){
28     dfn[x]=low[x]=++tim;
29     st[++top]=x;
30     vis[x]=1;
31     for(int i=first[x];i;i=nxt[i]){
32         if(!dfn[v[i]]){
33             tarjan(v[i]);
34             low[x]=min(low[x],low[v[i]]);
35         }
36         else if(vis[v[i]]) low[x]=min(low[x],dfn[v[i]]);
37     }
38     if(low[x]==dfn[x]){
39         bl[x]=++sz;
40         b[sz]=w[x];
41         vis[x]=0;
42         while(st[top]!=x){
43             vis[st[top]]=0;
44             b[sz]+=w[st[top]];
45             bl[st[top--]]=sz;
46         }
47         --top;
48     }
49 }
50 
51 void rebuild(){
52     memset(v,0,sizeof(v));
53     memset(nxt,0,sizeof(nxt));
54     memset(first,0,sizeof(first));
55     cnt=0;
56     for(int i=1;i<=m;i++) if(bl[aa[i]]!=bl[bb[i]]) add(bl[aa[i]],bl[bb[i]]);
57 }
58 
59 int dis[N],q[N*10];
60 int inq[N];
61 void spfa(int s){
62     for(int i=1;i<=sz;i++) dis[i]=b[i];
63     inq[s]=1;q[1]=s;
64     int head=1,tail=2;
65     while(head!=tail){
66         int x=q[head++];inq[x]=0;
67         if(head==N*10) head=1;
68         for(int i=first[x];i;i=nxt[i])
69             if(dis[x]+b[v[i]]>dis[v[i]]){
70                 dis[v[i]]=dis[x]+b[v[i]];
71                 if(!inq[v[i]]){
72                     q[tail++]=v[i];inq[v[i]]=1;
73                     if(tail==N*10) tail=1;
74                 }
75             }
76     }
77 }
78 
79 int main(){
80     read(n);read(m);
81     for(int i=1;i<=m;i++){
82         read(aa[i]);read(bb[i]);
83         add(aa[i],bb[i]);
84     }
85     for(int i=1;i<=n;i++) read(w[i]);
86     read(s);read(p);
87     for(int i=1;i<=p;i++) read(bar[i]);
88     for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
89     rebuild();spfa(bl[s]);
90     int ans=0;
91     for(int i=1;i<=p;i++) ans=max(ans,dis[bl[bar[i]]]);
92     printf("%d",ans);
93     return 0;
94 }
Code

 

posted @ 2018-05-26 16:17  lyf2  阅读(121)  评论(0编辑  收藏  举报