bzoj1179[Apio2009]Atm

bzoj1179[Apio2009]Atm

题意:

给个有向图,每个点有个点权,有些点有酒吧。现在求一个人从任意一点出发获得点权的最大和。要求每个点的点权只能获得一次,且路径最后必须在酒吧结束,可以重复经过点和边。n,m≤500000。

题解:

tarjan缩点之后跑spfa,注意不能用dijkstra,因为求正权边的最长路相当于求最短路时有负权边。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <stack>
 5 #include <queue>
 6 #define inc(i,j,k) for(int i=j;i<=k;i++)
 7 #define maxn 500010
 8 #define INF 0x3fffffff
 9 using namespace std;
10 
11 inline int read(){
12     char ch=getchar(); int f=1,x=0;
13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
14     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
15     return f*x;
16 }
17 struct e{int t,n;}es[2][maxn]; int g[2][maxn],ess[2];
18 void pe(int f,int t,bool o){es[o][++ess[o]]=(e){t,g[o][f]}; g[o][f]=ess[o];}
19 int v[2][maxn],scc[maxn],tot,n,m,s,p,ans;
20 bool ins[maxn]; int tim,low[maxn],dfn[maxn]; stack<int>st;
21 void tarjan(int x){
22     ins[x]=1; low[x]=dfn[x]=++tim; st.push(x);
23     for(int i=g[0][x];i;i=es[0][i].n){
24         if(!dfn[es[0][i].t])tarjan(es[0][i].t),low[x]=min(low[x],low[es[0][i].t]);
25         else if(ins[es[0][i].t])low[x]=min(low[x],dfn[es[0][i].t]);
26     }
27     if(low[x]==dfn[x]){
28         tot++;
29         while(!st.empty()){
30             int y=st.top(); st.pop(); ins[y]=0; scc[y]=tot;
31             v[1][tot]+=v[0][y]; if(x==y)break;
32         }
33     }
34 }
35 int d[maxn]; bool inq[maxn]; deque<int>q;
36 void spfa(int s){
37     inc(i,1,tot)d[i]=-1; d[s]=v[1][s]; inq[s]=1; q.push_back(s);
38     while(!q.empty()){
39         int x=q.front(); q.pop_front(); inq[x]=0;
40         for(int i=g[1][x];i;i=es[1][i].n)if(d[es[1][i].t]<d[x]+v[1][es[1][i].t]){
41             d[es[1][i].t]=d[x]+v[1][es[1][i].t];
42             if(!inq[es[1][i].t]){
43                 if(!q.empty()&&d[es[1][i].t]<d[q.front()])q.push_front(es[1][i].t);else q.push_back(es[1][i].t);
44                 inq[es[1][i].t]=1;
45             }
46         }
47     }
48 }
49 int main(){
50     n=read(); m=read(); inc(i,1,m){int x=read(),y=read(); pe(x,y,0);} inc(i,1,n)v[0][i]=read();
51     s=read(); p=read(); inc(i,1,n)if(!dfn[i])tarjan(i);
52     inc(i,1,n){
53         for(int j=g[0][i];j;j=es[0][j].n)
54             if(scc[i]!=scc[es[0][j].t])pe(scc[i],scc[es[0][j].t],1);
55     }
56     spfa(scc[s]); inc(i,1,p){int x=read(); if(d[scc[x]]!=-1)ans=max(ans,d[scc[x]]);}
57     printf("%d",ans); return 0;
58 }

 

20161114

posted @ 2016-11-15 20:29  YuanZiming  阅读(188)  评论(0编辑  收藏  举报