• Spfa求负环


    简介

    对于一个不存在负环的图,从起点到任意一个点最短距离经过的点最多只有 n 个。用 cnt[i] 表示从起点(假设是 1)到i的最短距离包含点的个数,初始化 cnt[1]=1,那么当我们能够用点u松弛点v时,松弛时同时更新cnt[v] = cnt[u]+1,若发现此时 cnt[v] > n,那么就存在负环
    还有一种方法是记录每个点的入队次数,入队次数大于 n 就说明有负环,但是这样做一般都要比上面的方法慢。举个例子,在一个由 n 个点构成的负环中,这个方法要绕环n次,而上面的方法绕环 1 次就行了

    例题

    Luogu-P3385

    模板题
    第一种方案

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #include<cstring>
    #include<algorithm>
    #define lson x<<1
    #define rson x<<1|1
    #define ll long long
    #define rint register int
    #define mid  ((L + R) >> 1)
    using namespace std;
    template <typename xxx> inline void read(xxx &x) {
    	char c = getchar(),f = 1;x = 0;
    	for(;c ^ '-' && !isdigit(c);c = getchar());
    	if(c == '-') c = getchar(),f = -1;
    	for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
    	x *= f;
    }
    template<typename xxx>void print(xxx x)
    {
        if(x<0){putchar('-');x=-x;}
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    const int maxn = 100010;
    const int inf = 0x7fffffff;
    const int mod = 1e9 + 7;
    struct edge {
    	int to,last,val;
    }e[maxn]; 
    int head[maxn],tot;
    inline void add(int from,int to,int val) {
    	++tot;
    	e[tot].to = to;
    	e[tot].val = val;
    	e[tot].last = head[from];
    	head[from] = tot;
    }
    int n,m;
    int dis[maxn],vis[maxn],tim[maxn];
    inline int spfa() {
    	queue<int>q;
    	for(rint i = 0;i <= n; ++i) {
    		dis[i] = inf;
    		vis[i] = 0;
    		tim[i] = 0;
    	} 
    	q.push(1);dis[1] = 0;tim[1] = 1;
    	while(q.size()) {
    		int x = q.front();q.pop();vis[x] = 0;
    		for(rint i = head[x];i;i = e[i].last) {
    			if(dis[e[i].to] > dis[x] + e[i].val) {
    				dis[e[i].to] = dis[x] + e[i].val;
    				tim[e[i].to] = tim[x] + 1;
    				if(tim[e[i].to] > n) return 1;
    				if(!vis[e[i].to]) {
    					vis[e[i].to] = 1;
    					q.push(e[i].to);
    				}
    			}
    		}
    	}
    	return 0;
    }
    int main() {
    	int t;read(t);
    	while(t--) {
    		tot = 0;
    		memset(head,0,sizeof(head));
    		read(n);read(m);
    		for(rint i = 1;i <= m; ++i) {
    			int a,b,c;
    			read(a);read(b);read(c);
    			add(a,b,c);
    			if(c >= 0) add(b,a,c);
    		}
    		if(spfa()) printf("YE5
    ");
    		else printf("N0
    ");
    	}
    	return 0;
    }
    /*
    
    */
    

    第二种方案(实测着实慢很多)

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #include<cstring>
    #include<algorithm>
    #define lson x<<1
    #define rson x<<1|1
    #define ll long long
    #define rint register int
    #define mid  ((L + R) >> 1)
    using namespace std;
    template <typename xxx> inline void read(xxx &x) {
    	char c = getchar(),f = 1;x = 0;
    	for(;c ^ '-' && !isdigit(c);c = getchar());
    	if(c == '-') c = getchar(),f = -1;
    	for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
    	x *= f;
    }
    template<typename xxx>void print(xxx x)
    {
        if(x<0){putchar('-');x=-x;}
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    const int maxn = 100010;
    const int inf = 0x7fffffff;
    const int mod = 1e9 + 7;
    struct edge {
    	int to,last,val;
    }e[maxn]; 
    int head[maxn],tot;
    inline void add(int from,int to,int val) {
    	++tot;
    	e[tot].to = to;
    	e[tot].val = val;
    	e[tot].last = head[from];
    	head[from] = tot;
    }
    int n,m;
    int dis[maxn],vis[maxn],tim[maxn];
    inline int spfa() {
    	queue<int>q;
    	for(rint i = 0;i <= n; ++i) {
    		dis[i] = inf;
    		vis[i] = 0;
    		tim[i] = 0;
    	} 
    	q.push(1);dis[1] = 0;
    	while(q.size()) {
    		int x = q.front();q.pop();vis[x] = 0;
    		if(tim[x] == n) return 1;
    		++tim[x];
    		for(rint i = head[x];i;i = e[i].last) {
    			if(dis[e[i].to] > dis[x] + e[i].val) {
    				dis[e[i].to] = dis[x] + e[i].val;
    				if(!vis[e[i].to]) {
    					vis[e[i].to] = 1;
    					q.push(e[i].to);
    				}
    			}
    		}
    	}
    	return 0;
    }
    int main() {
    //	freopen("my.out","w",stdout);
    	int t;read(t);
    	while(t--) {
    		tot = 0;
    		memset(head,0,sizeof(head));
    		read(n);read(m);
    		for(rint i = 1;i <= m; ++i) {
    			int a,b,c;
    			read(a);read(b);read(c);
    			add(a,b,c);
    			if(c >= 0) add(b,a,c);
    		}
    		if(spfa()) printf("YE5
    ");
    		else printf("N0
    ");
    	}
    	return 0;
    }
    /*
    
    */
    
    
  • 相关阅读:
    物联网解决方案
    热门研究方向
    LC滤波器简单设计法
    LC滤波电路分析,LC滤波电路原理及其时间常数的计算
    ams1117资料汇总
    杂项
    关于天线长度及LC值的计算
    稳压二极管、肖特基二极管、静电保护二极管、TVS管
    SPI、I2C、I2S、UART、GPIO、SDIO、CAN、JTAG的区别及使用方法。
    单片机串口通信电平不匹配的解决电路,5V 3.3V串口通讯
  • 原文地址:https://www.cnblogs.com/Thomastine/p/11860974.html
Copyright © 2020-2023  润新知