BZOJ 1179: [Apio2009]Atm
解题思路
今天这是咋了。。写了一堆假算法给了一堆假分。我竟然刚开始傻不拉几的写了个dijkstra跑最长路,结果87分???后面被告知只有spfa能跑最长路,并且需要将点权化为边权。。做法是因为所有atm都是非负数,所以不抢白不抢,我们考虑缩点。缩完点之后spfa最长路即可。多亏GhostCai神,要不得调几天估计。。。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
using namespace std;
const int MAXN = 500005;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,a[MAXN],Val[MAXN];
int head[MAXN],cnt,w[MAXN];
int nxt[MAXN],to[MAXN];
int nxt_[MAXN],to_[MAXN];
int head_[MAXN],cnt_;
int dfn[MAXN],low[MAXN];
int dis[MAXN],col[MAXN],col_num;
int stk[MAXN],top,num,st,ans;
int S,P,xx[MAXN],yy[MAXN];
bool vis[MAXN],b[MAXN],Bar[MAXN];
inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}
inline void add_(int bg,int ed,int v){
to_[++cnt_]=ed,w[cnt_]=v,nxt_[cnt_]=head_[bg],head_[bg]=cnt_;
}
inline void tarjan(int x){
dfn[x]=low[x]=++num;
vis[x]=1;stk[++top]=x;
for(register int i=head[x];i;i=nxt[i]){
int u=to[i];
if(!dfn[u]){
tarjan(u);
low[x]=min(low[x],low[u]);
}
else if(vis[u])
low[x]=min(low[x],dfn[u]);
}
if(dfn[x]==low[x]){
col[x]=++col_num;
while(stk[top]!=x){
vis[stk[top]]=0;
col[stk[top--]]=col_num;
}
vis[x]=0;
top--;
}
}
inline void spfa(){
memset(vis,false,sizeof(vis));
queue<int> Q;
Q.push(st);dis[st]=Val[st];vis[st]=1;
while(!Q.empty()){
int x=Q.front();Q.pop();
// cout<<x<<endl;
for(register int i=head_[x];i;i=nxt_[i]){
int u=to_[i];
if(dis[x]+w[i]>dis[u]){
dis[u]=dis[x]+w[i];
if(!vis[u]){
vis[u]=1;
Q.push(u);
}
}
} vis[x]=0;
}
}
int main(){
// freopen("2.in","r",stdin);
n=rd();m=rd();
for(register int i=1;i<=m;i++){
int x=rd(),y=rd();
xx[i]=x;yy[i]=y;
add(x,y);
}
for(register int i=1;i<=n;i++) {a[i]=rd();if(!dfn[i]) tarjan(i);}
// for(register int i=1;i<=n;i++) cout<<col[i]<<" ";
S=rd();P=rd();
for(register int i=1;i<=P;i++){
int x=rd();
b[x]=1;
}
for(register int i=1;i<=n;i++)
Val[col[i]]+=a[i];
for(register int i=1;i<=m;i++){
int x=xx[i],y=yy[i];
if(b[x]) Bar[col[x]]=1;
if(b[y]) Bar[col[y]]=1;
if(x==S) st=col[x];
if(y==S) st=col[y];
if(col[x]!=col[y]) add_(col[x],col[y],Val[col[y]]);
}
// for(register int i=1;i<=col_num;i++)
// cout<<Bar[i]<<" "<<Val[i]<<endl;
spfa();
for(register int i=1;i<=col_num;i++)
if(Bar[i]) ans=max(ans,dis[i]);
printf("%d",ans);
return 0;
}