论怎么记住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;
}

posted @ 2018-03-07 19:30  Eliza_Herb  阅读(91)  评论(0编辑  收藏  举报