博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P3387 缩点模板(缩点+记忆化搜索)
阅读量:4880 次
发布时间:2019-06-11

本文共 2281 字,大约阅读时间需要 7 分钟。

题目链接:

如果你还不会Tarjan缩点,我建议你还是先看看这篇博客:

或者过一段时间再来

首先我们分析题目,要求出图中的一条路径上点权之和最大的路径的点权之和

那么我们首先可以明确涂上如果有一个环,就一定要走完

或者说有强连通分量的话就要走完,我们便自然而然的想到了割点

最后处理的话就是一个简单的记忆化搜索

下面给出代码:

#include
#include
#include
#include
#include
#include
#include
using namespace std;inline int min(int a,int b){ return a
b?a:b;}inline int rd(){ int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f;}inline void write(int x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ;}int n,m;int v[100006];int head1[100006],nxt1[200006],to1[200006];int total1=0;void add1(int x,int y){ total1++; to1[total1]=y; nxt1[total1]=head1[x]; head1[x]=total1; return ;}int dfn[100006],low[100006];int color[100006];int tot=0;int color_cnt=0;int book[100006];int sta[100006];int v2[100006];int size=0;void Tarjan(int x,int fa){ //Tarjan模板 low[x]=dfn[x]=++tot; sta[++size]=x; book[x]=1; for(int e=head1[x];e;e=nxt1[e]){ if(!dfn[to1[e]]){ Tarjan(to1[e],x); low[x]=min(low[x],low[to1[e]]); } else if(book[to1[e]]) low[x]=min(low[x],dfn[to1[e]]); } if(dfn[x]==low[x]){ color[x]=++color_cnt; v2[color_cnt]=v[x]; book[x]=0; while(sta[size]!=x){ color[sta[size]]=color_cnt; book[sta[size]]=0; v2[color_cnt]+=v[sta[size]];//这个点的权值的计算,根据题目来确定 size--; } size--; } return ;}int head2[100006],nxt2[200006],to2[200006];int total2=0;void add2(int x,int y){ total2++; to2[total2]=y; nxt2[total2]=head2[x]; head2[x]=total2; return ;}void change(){ for(int i=1;i<=n;i++){ for(int e=head1[i];e;e=nxt1[e]){ if(color[i]!=color[to1[e]]){ add2(color[i],color[to1[e]]);//将两个点连边 } } } return ;}int dis[100006];void dfs(int x){ if(dis[x]) return ; int sum=0; dis[x]=v2[x]; for(int e=head2[x];e;e=nxt2[e]){ if(!dis[to2[e]]) dfs(to2[e]); sum=max(sum,dis[to2[e]]); } dis[x]+=sum; return ;}int main(){ n=rd(),m=rd(); for(int i=1;i<=n;i++) v[i]=rd();//得到点权 for(int i=1;i<=m;i++){ int x=rd(),y=rd(); add1(x,y);//有向边 } for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i,0); change(); int ans=0; for(int i=1;i<=color_cnt;i++){ if(!dis[i]){ dfs(i); ans=max(ans,dis[i]); } } write(ans); return 0;}

 

转载于:https://www.cnblogs.com/WWHHTT/p/9827496.html

你可能感兴趣的文章
HDU 1272 小希的迷宫
查看>>
hdu 5412 CRB and Queries(整体二分)
查看>>
CentOS如何安装linux桌面?
查看>>
Speech and Booth Demo in Maker Faire Shenzhen 2018
查看>>
bzoj 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘
查看>>
bzoj 2281: [Sdoi2011]黑白棋
查看>>
bzoj 4475: [Jsoi2015]子集选取
查看>>
团队开发7
查看>>
java之静态代理与动态代理
查看>>
软件测试2019:第四次作业
查看>>
201571030335 + 小学四则运算练习软件项目报告
查看>>
不用代码就能实现get与post
查看>>
发现一个强大的可视化第三方库pyecharts
查看>>
团队项目第一阶段冲刺站立会议03
查看>>
Android Material Design控件学习(二)——NavigationView的学习和使用
查看>>
ActiveMQ介绍
查看>>
FineUI(专业版)新增 5 款 Metro 皮肤,邀您共赏!
查看>>
Java生鲜电商平台-订单表的设计
查看>>
gdb基本调试命令
查看>>
互联网开放平台API安全设计
查看>>