【强连通分量+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 }
View Code

 

posted @ 2015-06-04 23:32  CyanNode  阅读(239)  评论(0编辑  收藏  举报