论怎么记住tarjan的板子
小时候,爸爸告诉我,背课文啊,要知道课文的逻辑。以逻辑为序记忆的话,课文可以记得又快又牢。
我不是那种天赋异禀的记代码强者是吧。。。那么按这种方式来记板子,当然是不二(二货)选择。
首先,tarjan板子的思路:读入边(图论模板)-->dfs(遇点入栈用到栈,用到了low和dfn)-->搜到scc后出栈(用到栈,开scc的一系列性质)-->重新建图(再开一组图论模板)-->完毕,接下来请客官慢慢享用模板带来的HAPPY。接下来可以打一个work函数什么的,代码看起来会更简洁。
另外,按照功能的不同,把变量一组一组地设好,可以避免把变量打反什么的bug。
--------------------------------------------------------------------------------
下面是luoguP3387的代码,曾经手残的地方加了注释
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdlib>
#define MAXN 10005
#define MAXM 100005
using namespace std;
int n,m,w[MAXN],f[MAXN];
struct data{
int to,next;
}e[MAXM],d[MAXM];
int head[MAXN];
int cnt,top;/////
int low[MAXN],dfn[MAXN];
int scc,belong[MAXN],hav[MAXN];
int h[MAXM],q[MAXN];
bool vis[MAXN],inq[MAXN];
void dfs(int a){
int now;
inq[a]=vis[a]=1;
dfn[a]=low[a]=++cnt;
q[++top]=a;
int c=head[a];
while(c){
if(!vis[e[c].to ]){
dfs(e[c].to );
low[a]=min(low[a],low[e[c].to ]);
}
else if(inq[e[c].to ]) low[a]=min(low[a],dfn[e[c].to ]);
c=e[c].next ;
}
// if(q[top]==a)
if(low[a]==dfn[a]){
++scc;/////
// printf("%d: ",scc);
while(now!=a){
now=q[top--];
// printf("%d ",now);
belong[now]=scc;
inq[now]=0;
hav[scc]+=w[now];
}
// printf(" %d\n",hav[scc]);
}
}
void rebuild(){
cnt=0;
for(int i=1;i<=n;i++){
int c=head[i];
while(c){
if(belong[i]!=belong[e[c].to ]){
d[++cnt].to =belong[e[c].to ];/////
d[cnt].next =h[belong[i]];/////
h[belong[i]]=cnt;/////
}
c=e[c].next ;////
}
}
}
void tarjan(){
for(int i=1;i<=n;i++){
if(!vis[i]) dfs(i);
}
rebuild();
}
void work(int a){///
if(f[a]) return;
f[a]=hav[a];/////
int maxsum=0;
for(int i=h[a];i;i=d[i].next ){
if(!f[d[i].to ]) work(d[i].to );
maxsum=max(maxsum,f[d[i].to ]);
}
f[a]+=maxsum;
// printf("%d %d\n",a,f[a]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
int u,v;
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
e[++cnt].to =v;
e[cnt].next =head[u];
head[u]=cnt;
}
/*for(int i=1;i<=cnt;i++){
printf("%d ",e[i].to );
}
printf("\n");*/
tarjan();
int ans=0;
for(int i=1;i<=scc;i++){
if(!f[i]) work(i);
ans=max(f[i],ans);
}
printf("%d",ans);
return 0;
}