【强连通分量+spfa】Bzoj1179 Apio2009 Atm

Description

Sulotion

显然缩强连通分量,然后求最长路,虽然是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 }

时间: 2024-08-27 06:19:37

【强连通分量+spfa】Bzoj1179 Apio2009 Atm的相关文章

【强连通分量&#183;Tarjan】bzoj1179: [Apio2009]Atm

新博的第一发! 因为这几天切了几道强连通分量,所以从这里begin [题目描述] Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定,在每个路口都设立了一个Siruseri 银行的ATM 取款机.令人奇怪的是,Siruseri的酒吧也都设在路口,虽然并不是每个路口都设有酒吧.Banditji 计划实施Siruseri 有史以来最惊天动地的ATM 抢劫.他将从市中心出发,沿着单向道路行驶,抢劫所有他途径的ATM 机,最终他将在一个酒吧庆祝他的胜利.使用高超的黑客技术,他获

BZOJ1179 : [Apio2009]Atm 缩点+spfa

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2069  Solved: 826[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来

tarjan+spfa最短路 BZOJ1179 [Apio2009] Atm

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 3641  Solved: 1552[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下

bzoj1179: [Apio2009]Atm

tarjan缩点就是DAG上求最长路把...然而我并不会求...只会写spfa了... #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<stack> #include<queue> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #defin

【强联通分量缩点】【最短路】【spfa】bzoj1179 [Apio2009]Atm

缩点后转化成 DAG图上的单源最长路问题.spfa/dp随便. 1 #include<cstdio> 2 #include<queue> 3 #include<algorithm> 4 #include<vector> 5 #include<cstring> 6 using namespace std; 7 int cmp[500001],sum,n,m,Us[500001],Vs[500001],t,w[500001],sta,k,ans,di

[BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)

传送门 题意 N个点M条边的有向图 每个点有点权 从某一个结点出发 问能获得的最大点权和 一个点的点权最多被计算一次 N<=500000 M<=500000 思路 先tarjan缩点,然后就形成一个dag,无环,所以直接spfa求最长路就行. 也可以先缩点,然后拓扑排序 + dp 搞. 代码 1 #include <map> 2 #include <queue> 3 #include <stack> 4 #include <cstdio> 5 #

[BZOJ1179][APIO2009][强连通分量Tarjan+spfa]ATM

[BZOJ1179][APIO2009]ATM Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,表示Banditji从市中心开始到某个

【bzoj1179】[Apio2009]抢掠计划atm 强连通分量缩点+spfa

Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来一行包含两个整数S.P,S表示市中心的编号,也就是出发的路口.P表示酒吧数目.接下来的一行中有P个整数,表示P个有酒吧的路口的编号 Output 输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数. Sample

缩点+spfa最长路【bzoj】 1179: [Apio2009]Atm

[bzoj] 1179: [Apio2009]Atm Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧.Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫.他将从市中心 出发,沿着单向道路行驶,抢劫所有他 途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利.使用高超