• acwing 904. 虫洞(spfa判断负环,单链表写法)


    题目传送门

    题目描述

    农夫约翰在巡视他的众多农场时,发现了很多令人惊叹的虫洞。

    虫洞非常奇特,它可以看作是一条 单向 路径,通过它可以使你回到过去的某个时刻(相对于你进入虫洞之前)。

    农夫约翰的每个农场中包含 NN 片田地,MM 条路径(双向)以及 WW 个虫洞。

    现在农夫约翰希望能够从农场中的某片田地出发,经过一些路径和虫洞回到过去,并在他的出发时刻之前赶到他的出发地。

    他希望能够看到出发之前的自己。

    请你判断一下约翰能否做到这一点。

    下面我们将给你提供约翰拥有的农场数量 FF,以及每个农场的完整信息。

    已知走过任何一条路径所花费的时间都不超过 1000010000 秒,任何虫洞将他带回的时间都不会超过 1000010000 秒。

    输入格式

    第一行包含整数 FF,表示约翰共有 FF 个农场。

    对于每个农场,第一行包含三个整数 N,M,WN,M,W。

    接下来 MM 行,每行包含三个整数 S,E,TS,E,T,表示田地 SS 和 EE 之间存在一条路径,经过这条路径所花的时间为 TT。

    再接下来 WW 行,每行包含三个整数 S,E,TS,E,T,表示存在一条从田地 SS 走到田地 EE 的虫洞,走过这条虫洞,可以回到 TT 秒之间。

    输出格式

    输出共 FF 行,每行输出一个结果。

    如果约翰能够在出发时刻之前回到出发地,则输出 YES,否则输出 NO

    数据范围

    1≤F≤51≤F≤5
    1≤N≤5001≤N≤500,
    1≤M≤25001≤M≤2500,
    1≤W≤2001≤W≤200,
    1≤T≤100001≤T≤10000,
    1≤S,E≤N1≤S,E≤N

    输入样例:

    2
    3 3 1
    1 2 2
    1 3 4
    2 3 1
    3 1 3
    3 2 1
    1 2 3
    2 3 4
    3 1 8
    

    输出样例:

    NO
    YES
    

    spfa判断负环

    分析

    代码

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring> 
    using namespace std;
    const int N = 510, M = 5210; // 
    int h[N], e[M], w[M], ne[M], idx = 0; 
    int dist[N]; // dist[i]表示到1到i的最短路的距离 
    int cnt[N]; // cnt[i]表示到i点最短路的边数 
    bool st[N]; // 
    int n;
    void add(int a, int b, int c)
    {
    	e[idx] = b;
    	w[idx] = c;
    	ne[idx] = h[a];
    	h[a] = idx++;
    }
    
    bool spfa()
    {
    	memset(dist, 0, sizeof dist);
    	memset(cnt, 0, sizeof cnt);
    	memset(st, 0, sizeof st);
    	
    	queue<int> q;
    	for(int i = 1; i <= n; i++)
    	{
    		st[i] = true;
    		q.push(i);
    	}
    	
    	while(q.size())
    	{
    		int t = q.front();
    		q.pop();
    		
    		st[t] = false; // t不在队列中了
    		
    		for(int i = h[t]; i != -1; i = ne[i])
    		{
    			int j = e[i];
    			if(dist[j] > dist[t] + w[i])
    			{
    				dist[j] = dist[t] + w[i];
    				cnt[j] = cnt[t] + 1;
    				
    				if(cnt[j] >= n) return true;
    				
    				if(!st[j])
    				{
    					q.push(j);
    					st[j] = true;	
    				}	
    			}	
    		} 
    	}
    	return false;
    }
    
    
    int T, m1, m2;
    
    
    void init()
    {
    	memset(h, -1, sizeof h);
    	memset(e, 0, sizeof e);
    	memset(ne, 0, sizeof ne);
    	memset(w, 0, sizeof w);
    	idx = 0;
    }
    
    int main()
    {
    	memset(h, -1, sizeof h);
    	
    	
    	scanf("%d", &T);
    	while(T--)
    	{
    		// 一定这里初始化,或者调用init() 
    		memset(h, -1, sizeof h);
    		idx = 0;
    		
    		
    		int s, t, w;
    		scanf("%d%d%d", &n, &m1, &m2);
    		while(m1 --)
    		{
    			scanf("%d%d%d", &s, &t, &w);
    			add(s, t, w), add(t, s, w); // 无向图	
    		}	
    		while(m2 --)
    		{
    			scanf("%d%d%d", &s, &t, &w);
    			add(s, t, -w); // 负边 
    		}
    		if(spfa()) puts("YES");
    		else	   puts("NO"); 
    	} 
    	return 0;
    }
    

    时间复杂度

    参考文章

  • 相关阅读:
    hdu 5015
    hdu 2276
    hdu 6197 array array array LIS
    poj 3070
    codefroce 854 A.Fraction
    sql数据库发布、订阅同步方式操作
    python排序(冒泡、直接选择、直接插入等)
    忘记mysql数据库密码时进行修改方法
    Word中图片自动编号且与文中引用的编号对应
    解决电脑本地网络连接显示红叉又可上网问题
  • 原文地址:https://www.cnblogs.com/VanHa0101/p/16026658.html
Copyright © 2020-2023  润新知