• 洛谷P3385 【模板】负环(DFS求环)


    洛谷题目传送门

    HNOI爆零前回刷模板题

    非常不正经的题目,目前并没有合适的优秀算法,就算是大家公认的dfs(还是不要强行叫dfs-spfa吧,概念应该不一样,这就是暴力dfs松弛答案)

    但是对于随机数据来说,dfs有着优秀的效率,可以快速发现负环并退出

    从每个点开始暴力dfs,记一个bool数组ins表示每个点是否在搜索栈中。如果发现可以松弛并且踏进了已经在栈中的点就说明找到了负环。

    注意几点:

    1. YE5和N0 2333

    2. dis初始化为0,因为只要判负环,正权一开始并不用松弛

    3. 因为并没有说图连通,所以每个点都要作为起点跑一遍dfs

    4. 每个点都跑一遍有点麻烦,可以加一个剪枝,标记已经访问过的点,如果这个点之前已经松弛过了就不用再跑dfs了,反正也松弛不了。当然实际优化效果不是很理想,因为这个数组每次都要清空。。。。。。

    #include<cstdio>
    #include<cstring>
    #define RG register
    #define R RG int
    #define gc if(++pi==iend)fread(pi=ibuf,1,SZ,stdin)
    #define add(X,Y,V) v[++p]=V,to[p]=Y,ne[p]=he[X],he[X]=p
    const int SZ=1<<20,N=200009,M=N<<1;
    char ibuf[SZ],*iend=ibuf+SZ,*pi=iend-1;
    int he[N],ne[M],to[M],v[M],d[N];
    bool ins[N],vis[N];
    inline int in(){
    	gc;while(*pi<'-')gc;
    	RG bool f=*pi=='-';if(f)gc;
    	R x=*pi&15;gc;
    	while(*pi>'-'){x*=10;x+=*pi&15;gc;}
    	return f?-x:x;
    }
    bool dfs(R x){
    	vis[x]=ins[x]=1;
    	for(R y,i=he[x];i;i=ne[i])
    		if(d[y=to[i]]>d[x]+v[i]){
    			d[y]=d[x]+v[i];//松弛
    			if(ins[y]||dfs(y))return !(ins[x]=0);//退回来记得把ins变成0
    		}
    	return ins[x]=0;
    }
    int main(){
    	R T=in(),n,m,p,a,b,w,i;
    	while(T--){
    		n=in();m=in();p=0;
    		while(m--){
    			a=in();b=in();w=in();
    			add(a,b,w);
    			if(w>=0)add(b,a,w);
    		}
    		for(i=1;i<=n;++i)
    			if(!vis[i]&&dfs(i)){
    				puts("YE5");
    				goto E;
    			}
    		puts("N0");
    	  E:memset(he,0,(n+1)<<2);//都要清空
    		memset(d,0,(n+1)<<2);
    		memset(vis,0,n+1);
    	}
    	return 0;
    }
    
  • 相关阅读:
    git工具命令整理
    使用nodeJs操作redis
    electron 7.x 设置开发环境与生产模式 隐藏菜单栏和开发者工具 devtools
    electron 打包问题 解决
    sso单点登录之跨域cookie共享 (跨域缓存共享)
    浏览器线程执行顺序
    JS如何将变量作为一个对象的Key
    DevOps流程的简单总结
    通过key 寻找数组内对象的某一项
    根据key查找对象数组中符合的一项 返回对象(递归)
  • 原文地址:https://www.cnblogs.com/flashhu/p/8824202.html
Copyright © 2020-2023  润新知