zoukankan      html  css  js  c++  java
  • 论怎么记住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
    ",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
    ",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("
    ");*/
    	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;
    }

  • 相关阅读:
    《代码阅读与实践》阅读笔记*part1
    HDFS JAVA API
    《需求工程》阅读笔记*part3
    《需求工程》阅读笔记*part2
    HDFS文件命令
    HOG特征+SVM行人检测
    winchecksec安装踩坑
    加壳:挂起方式创建进程
    内存写入注入
    远程线程注入
  • 原文地址:https://www.cnblogs.com/nishida-rin/p/12271144.html
Copyright © 2011-2022 走看看