【强连通分量+spfa】Bzoj1179 Apio2009 Atm
Description
Solution
显然缩强连通分量,然后求最长路,虽然是DAG但还是有点麻烦,于是用了spfa。
Code
重建图_数组写错好多次,感觉做这题也就是练了一下实现。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=5e+5; 5 6 int pre[maxn],low[maxn],clock; 7 int scc[maxn],val[maxn],cnt,a[maxn],t; 8 int head[maxn],f[maxn],e[maxn],nxt[maxn],k; 9 int adde(int u,int v){ 10 f[++k]=u,e[k]=v; 11 nxt[k]=head[u],head[u]=k; 12 } 13 int n,m,s,p; 14 int w[maxn],ok[maxn]; 15 16 int dfs(int u){ 17 //printf("%d\n",u); 18 pre[u]=low[u]=++clock; 19 a[++t]=u; 20 for(int i=head[u];i;i=nxt[i]){ 21 int v=e[i]; 22 if(!pre[v]){ 23 dfs(v); 24 low[u]=min(low[u],low[v]); 25 } 26 else if(!scc[v]){ 27 low[u]=min(low[u],pre[v]); 28 } 29 } 30 if(low[u]==pre[u]){ 31 ++cnt; 32 while(t){ 33 scc[a[t]]=cnt; 34 val[cnt]+=w[a[t]]; 35 if(a[t--]==u) break; 36 } 37 } 38 } 39 40 int ok_[maxn]; 41 int head_[maxn],e_[maxn],nxt_[maxn],k_; 42 int adde_(int u,int v){ 43 e_[++k_]=v; 44 nxt_[k_]=head_[u],head_[u]=k_; 45 } 46 47 int rebuild(){ 48 for(int i=1;i<=k;i++){ 49 int u=scc[f[i]],v=scc[e[i]]; 50 if(u!=v) adde_(u,v); 51 } 52 for(int i=1;i<=n;i++) 53 if(ok[i]) ok_[scc[i]]=1; 54 } 55 56 int q[maxn],d[maxn],inque[maxn],ans,h; 57 int spfa(){ 58 t=0; 59 s=scc[s]; 60 q[++t]=s; 61 inque[s]=1; 62 d[s]=val[s]; 63 ans=d[s]; 64 while(h<t){ 65 int u=q[++h]; 66 //printf("%d\n",u); 67 for(int i=head_[u];i;i=nxt_[i]){ 68 int v=e_[i]; 69 if(d[u]+val[v]>d[v]){ 70 //printf(" %d\n",v); 71 d[v]=d[u]+val[v]; 72 if(ok_[v]) ans=max(ans,d[v]); 73 if(!inque[v]) inque[v]=1,q[++t]=v; 74 } 75 } 76 inque[u]=0; 77 } 78 } 79 80 int main(){ 81 scanf("%d%d",&n,&m); 82 int u,v,x; 83 for(int i=1;i<=m;i++){ 84 scanf("%d%d",&u,&v); 85 adde(u,v); 86 } 87 for(int i=1;i<=n;i++) 88 scanf("%d",&w[i]); 89 scanf("%d%d",&s,&p); 90 for(int i=1;i<=p;i++) 91 scanf("%d",&x),ok[x]=1; 92 93 for(int i=1;i<=n;i++) 94 if(!pre[i]) dfs(i); 95 96 rebuild(); 97 spfa(); 98 printf("%d\n",ans); 99 return 0; 100 }