Codevs1161 抢掠计划
来源:互联网 发布:在线打电话软件 编辑:程序博客网 时间:2024/06/06 04:36
前言:这题A得挺值,不仅学会了tarjan以及递归转非递归,还熟悉了spfa,不错。
鸣谢:hzwer、t14t41t。
题目大意:给定一张有向有环图,有点权,求一条路上得到点权的最大值。
思路:一个强连通分量里的点权是全部能取得的,因此用tarjan进行缩点。最后求值时,可以用spfa求最长路,个人感觉也可以用拓扑序递推,我用的是spfa,具体的在程序中解释。
代码如下:
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<vector>#include<stack>using namespace std;const int maxn=600005;int n,m,source,p;vector<int> g[maxn],rg[maxn];/*g是原图,rg是重建图*/int atm[maxn],pub[maxn];stack<int> s,bs;/*s是tarjan的栈,bs是模拟系统栈*/int dex,cir=0,dfn[maxn],low[maxn],belong[maxn];int sum[maxn];bool in[maxn];void init(){ memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(in,0,sizeof(in)); scanf("%d%d",&n,&m); for (int i=1;i<=m;++i) { int a,b; scanf("%d%d",&a,&b); g[a].push_back(b); } for (int i=1;i<=n;++i) scanf("%d",&atm[i]); scanf("%d%d",&source,&p); for (int i=1;i<=p;++i) scanf("%d",&pub[i]);}/*void tarjan(int u){ low[u]=dfn[u]=++dex; s.push(u); in[u]=1; for (int i=0;i<g[u].size();++i) { if (!dfn[g[u][i]]) { tarjan(g[u][i]); low[u]=min(low[u],low[g[u][i]]); } else { if (in[g[u][i]]) { low[u]=min(low[u],dfn[g[u][i]]); } } } if (low[u]==dfn[u]) { cir++; int t=-1; while (t!=u) { t=s.top(); s.pop(); in[t]=0; belong[t]=cir; sum[cir]+=atm[t]; } }}*/ /*递归版tarjan*/void tarjan(int u){ dfn[u]=low[u]=++dex; bs.push(u); s.push(u); in[u]=1; while (!bs.empty()) { int t=bs.top(); for (int i=0;i<g[t].size();++i) { if (!dfn[g[t][i]]) { dfn[g[t][i]]=low[g[t][i]]=++dex; bs.push(g[t][i]); in[g[t][i]]=1; s.push(g[t][i]); break; /*在这里break,会有下面t!=top(),从而一直递归下去*/ } } if (t==bs.top()) { for (int i=0;i<g[t].size();++i) { if (dfn[g[t][i]]>dfn[t]) /*这里需要判断是不是后来的,递归版则不需要*/ low[t]=min(low[t],low[g[t][i]]); else if (in[g[t][i]]) low[t]=min(low[t],dfn[g[t][i]]); } if (dfn[t]==low[t]) { cir++; int now=-1; while (now!=t) { now=s.top(); belong[now]=cir; sum[cir]+=atm[now]; in[now]=0; s.pop(); } } bs.pop(); } }}void rebuild(){ for (int i=1;i<=n;++i) for (int j=0;j<g[i].size();++j) if (belong[i]!=belong[g[i][j]]) rg[belong[i]].push_back(belong[g[i][j]]);}int vis[maxn],fee[maxn];queue<int> q;void spfa(int s){ memset(vis,0,sizeof(vis)); memset(fee,0,sizeof(fee)); q.push(s); vis[s]=1; fee[s]=sum[s]; while (!q.empty()) { int h=q.front(); vis[h]=0; q.pop(); for (int i=0;i<rg[h].size();++i) { if (fee[rg[h][i]]<fee[h]+sum[rg[h][i]]) { fee[rg[h][i]]=fee[h]+sum[rg[h][i]]; if (!vis[rg[h][i]]) { vis[rg[h][i]]=1; q.push(rg[h][i]); } } } } int ans=0; for (int i=1;i<=p;++i) { ans=max(ans,fee[belong[pub[i]]]); } printf("%d",ans);}int main(){ init(); for (int i=1;i<=n;++i) if (!dfn[i]) { /*不要写dex=0*/ tarjan(i); } rebuild(); spfa(belong[source]); return 0;}
0 0
- Codevs1161 抢掠计划
- 抢掠计划
- APIO2009 抢掠计划
- APIO2009 抢掠计划
- [APIO2009]抢掠计划
- P3627 [APIO2009]抢掠计划
- 省选专练APIO2009抢掠计划
- 【强连通分量】抢掠计划
- 【Bzoj1179】[Apio2009]抢掠计划atm
- 【APIO2009】【强连通分量】【DAG】抢掠计划
- 缩点+dp bzoj1179 apio抢掠计划
- 非递归!APIO2009atm[抢掠计划]题解
- 【APIO2009】BZOJ1179 BSOJ2468 CODEVS1611 抢掠计划
- [APIO2009]抢掠计划(tarjan+spfa)
- 【强连通缩点+最长路】抢掠计划
- APIO 2009 抢掠计划 强联通缩点+最长路
- P2255【L1 SOLO 第五场 APIO2009】抢掠计划
- APIO抢掠计划(浅谈Tarjan——(4))
- SAS里面的optmodel过程
- Android 项目实践(三)——数据库封装
- 小小君的C语言第四课
- ios面试题
- 微软官方网站提供 MASM 8.0软件包(x86)下载,有简体中文版
- Codevs1161 抢掠计划
- iOS单例设计模式
- 数组与字典的应用
- C++/Java__中类模板中的静态成员变量和静态成员函数
- python学习-数据分析2(分类型数据处理+SVM建模)
- CABasicAnimation的基本使用方法(移动·旋转·放大·缩小)
- 创建带Apache服务的Centos Docker镜像
- Windows命令启动MySQL“ 发生系统错误 5 ”
- 面向对象四大特征