1. 程式人生 > >BZOJ 1179 [Apio2009]Atm

BZOJ 1179 [Apio2009]Atm

tor oid size post sca cno con std class

題解:裸的縮點+最短路(DP)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=500009;
const int oo=1000000000;

int n,m;
int v[maxn];

int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

vector<int>G[maxn];
int dfsclock,scccnt;
int pre[maxn],lowlink[maxn],sccno[maxn];
int S[maxn],top;
void Dfs(int u){
	pre[u]=lowlink[u]=++dfsclock;
	S[++top]=u;
	
	for(int i=0;i<G[u].size();++i){
		int v=G[u][i];
		if(!pre[v]){
			Dfs(v);
			lowlink[u]=min(lowlink[u],lowlink[v]);
		}else if(!sccno[v]){
			lowlink[u]=min(lowlink[u],pre[v]);
		}
	}
	
	if(lowlink[u]==pre[u]){
		++scccnt;
		for(;;){
			int x=S[top--];
			sccno[x]=scccnt;
			if(x==u)break;
		}
	}
}

int isb[maxn];
int w[maxn];
void Tarjan(){
	for(int i=1;i<=n;++i){
		if(!pre[i])Dfs(i);
	}
	for(int i=1;i<=n;++i)w[sccno[i]]+=v[i];
	for(int u=1;u<=n;++u){
		for(int i=0;i<G[u].size();++i){
			int v=G[u][i];
			if(sccno[u]!=sccno[v])Addedge(sccno[u],sccno[v]);
		}
	}
}
int s;
queue<int>q;
int inq[maxn];
int d[maxn];
void Spfa(){
	for(int i=1;i<=scccnt;++i){
		d[i]=-oo;inq[i]=0;
	}
	d[s]=w[s];inq[s]=1;q.push(s);
	while(!q.empty()){
		int x=q.front();q.pop();inq[x]=0;
		for(int i=head[x];i;i=nex[i]){
			if(d[x]+w[to[i]]>d[to[i]]){
				d[to[i]]=d[x]+w[to[i]];
				if(!inq[to[i]]){
					inq[to[i]]=1;
					q.push(to[i]);
				}
			}
		}
	}
}

int main(){
	scanf("%d%d",&n,&m);
	while(m--){
		int x,y;
		scanf("%d%d",&x,&y);
		G[x].push_back(y);
	}
	for(int i=1;i<=n;++i)scanf("%d",&v[i]);
	Tarjan();
	
	scanf("%d%d",&s,&m);
	while(m--){
		int x;scanf("%d",&x);
		isb[sccno[x]]=1;
	}
	s=sccno[s];
	Spfa();
	int ans=-oo;
	for(int i=1;i<=scccnt;++i){
		if(isb[i])ans=max(ans,d[i]);
	}
	
	printf("%d\n",ans);
	return 0;
}

  

BZOJ 1179 [Apio2009]Atm