BZOJ 1179 APIO2009 ATM Tarjan+堆優化SPFA
阿新 • • 發佈:2019-02-11
題目大意:給定一個有向圖,每個點上有正權,求一條從起點出發到任意終點的路徑,要求路上的點權和最大(一個點權只能被加一次)
首先Tarjan縮點,易知一個強連通分量內任意一個點權拿到就可以拿到強連通分量內所有的點權
然後這個圖就沒有環了,SPFA跑最長路即可
邊數500W,所以要加堆優化
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 500500 using namespace std; struct edge{ int x,y; }edges[M]; struct abcd{ int to,next; }table[M<<1]; int head[M],tot; int n,m,a[M],ans; int s,k; int dpt[M],low[M],T,stack[M],top,v[M],belong[M],cnt,cash[M]; int f[M],heap[M],pos[M]; void Push_Up(int t) { while(t>1&&f[heap[t]]>f[heap[t>>1]]) swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t>>=1; } void Insert(int x) { heap[++top]=x; pos[x]=top; Push_Up(top); } void Pop() { pos[heap[1]]=0; heap[1]=heap[top--]; if(top) pos[heap[1]]=1; int t=2; while(t<=top) { if(t<top&&f[heap[t+1]]>f[heap[t]]) ++t; if(f[heap[t]]>f[heap[t>>1]]) swap(heap[t],heap[t>>1]),swap(pos[heap[t]],pos[heap[t>>1]]),t<<=1; else break; } } void SPFA() { int i; memset(f,0xef,sizeof f); f[belong[s]]=cash[belong[s]]; Insert(belong[s]); while(top) { int x=heap[1];Pop(); for(i=head[x];i;i=table[i].next) if(f[table[i].to]<f[x]+cash[table[i].to]) { f[table[i].to]=f[x]+cash[table[i].to]; if(!pos[table[i].to]) Insert(table[i].to); else Push_Up(pos[table[i].to]); } } } void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } void Tarjan(int x) { int i; dpt[x]=low[x]=++T; stack[++top]=x; for(i=head[x];i;i=table[i].next) { if(v[table[i].to]) continue; if(dpt[table[i].to]) low[x]=min(low[x],dpt[table[i].to]); else Tarjan(table[i].to),low[x]=min(low[x],low[table[i].to]); } if(dpt[x]==low[x]) { int t; ++cnt; do{ t=stack[top--]; v[t]=1; belong[t]=cnt; cash[cnt]+=a[t]; }while(t!=x); } } int main() { int i,x,y; cin>>n>>m; for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); edges[i].x=x; edges[i].y=y; Add(x,y); } for(i=1;i<=n;i++) scanf("%d",&a[i]); cin>>s>>k; Tarjan(s); memset(head,0,sizeof head);tot=0; for(i=1;i<=m;i++) if(belong[edges[i].x]!=belong[edges[i].y]) Add(belong[edges[i].x],belong[edges[i].y]); SPFA(); for(i=1;i<=k;i++) { scanf("%d",&x); ans=max(ans,f[belong[x]]); } cout<<ans<<endl; }