zoukankan      html  css  js  c++  java
  • POJ 3259 Wormholes (判负环)

    • 题意: 无向图加负的有向边,求是否存在负环
    • 思路:
      1. spfa: spfa是一直拿更新后的边来增广其他可达边,如果存在负环,则会一直增广,存下当前路径的长度,如果超过了n则说明一直在负环上增广,即存在负环
      2. floyd: 跑一遍Floyd,如果存在某个点到自己的距离为负,则存在负环(负环上的点走一遍负环,到自己的距离肯定为负)

    spfa:

    
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<algorithm>
    #define ll long long
    #define FOR(i,l,r) for(int i = l ; i <= r ;++i )
    #define inf 0x3f3f3f3f
    #define EPS (1e-9)
    #define ALL(T)  T.begin(),T.end()
    using namespace std;
    
    const int maxn = 5010;
    
    int n,m,w;
    
    struct Edge{
    	int to,next,w;
    }edge[maxn*10];
    int tot;
    int d[maxn],cnt[maxn],head[maxn];
    int v[maxn];
    
    void addEdge(int u,int v,int w){
    	edge[tot].to = v;
    	edge[tot].w = w;
    	edge[tot].next = head[u];
    	head[u] = tot++; 
    }
    
    bool spfa(){
    	queue<int> q;
    	memset(v,0,sizeof(v));
    	memset(cnt,0,sizeof(cnt));
    	d[1] = 0;
    	cnt[1] = 0; 
    	v[1] = 1;
    	q.push(1);
    	while(q.size()){
    		int x = q.front();	q.pop();
    		v[x] = 0;
    		for(int i=head[x];i!=-1;i=edge[i].next){
    			int y = edge[i].to;
    			int z = edge[i].w;
    			if(d[y]>d[x]+z){
    				d[y] = d[x]+z;
    				cnt[y] = cnt[x] + 1;
    				if(cnt[y]>n)
    					return true;
    				if(v[y]==0){
    					q.push(y);
    					v[y] =1;
    					// cnt[y]++;
    				}	
    			}
    		}
    	}
    	return false;
    }
    
    
    int main(){
    int t;
    cin >> t;
    while(t--){
    	cin >> n >> m >> w;
    	tot = 0;
    	int f,to,wet;
    	memset(head,-1,sizeof(head));
    	memset(d,inf,sizeof(d));
    	for(int i=1;i<=m;++i){
    		cin >> f >> to >> wet;
    		addEdge(f,to,wet);
    		addEdge(to,f,wet);
    	}
    	for(int i=1;i<=w;++i){
    		cin >> f >> to >> wet;
    		addEdge(f,to,-wet);
    	}
    	if(spfa())cout << "YES" << endl;
    	else cout <<"NO" << endl;
    }
    	
    	return 0;
    }
    
    

    floyd:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    
    const int maxn = 510;
    
    inline int read(){
       int s=0,w=1;
       char ch=getchar();
       while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
       return s*w;
    }
    
    int n,m,w;
    int g[maxn][maxn];
    inline int min(int a,int b){
    	return a>b? b:a;
    }
    bool floyd(){
    	for(int k=1;k<=n;++k){
    		for(int i=1;i<=n;++i){
    			for(int j=1;j<=n;++j){
    				if(g[i][j]>g[i][k]+g[k][j])
    					g[i][j] =  g[i][k]+g[k][j];
    			}
    			if(g[i][i]<0){
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    int main(){
    int t;
    t = read();
    while(t--){
    	n = read();	m = read();	w = read();
    	memset(g,0x3f,sizeof(g));
    	for(int i=1;i<=n;++i)	g[i][i] = 0;
    	int f,to,wet;
    	for(int i=1;i<=m;++i){
    		f = read();	to = read();	wet = read();
    		g[f][to] = wet<g[f][to] ? wet:g[f][to];
    		g[to][f] = g[f][to];
    	}
    	for(int i=1;i<=w;++i){
    		f = read();	to = read();	wet = read();
    		g[f][to] = -wet;
    	}
    
    	if(floyd())printf("YES
    ");
    	else printf("NO
    ");
    }
    	
    	return 0;
    }
    

    floyd加快读 1.6s用min会T,用三目运算符也会T,用if才能过神奇, spfa加cin 0.5s

    题目连接

  • 相关阅读:
    HDU4825/5536 [01 字典树/简单字典树更新]
    HDU 2017 多校联合Contest 3
    51nod 多重背包 [二进制优化]
    UVa 123042D Geometry 110 in 1! [平面几何]
    UVA 11796Dog Distance[平面几何]
    洛谷P1004 方格取数[多维dp]
    HDU 1576 A/B [逆元]
    POJ1006 中国剩余定理
    HDU 1573~3579 X问题&Hello Kiki[同余方程]
    一元线性同余方程组
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11274325.html
Copyright © 2011-2022 走看看