POJ - 3259 Wormholes SPFA负环模板题

题目链接

POJ-3259

题意

给出n个节点,m条双向道路,k条单向传送门,穿越道路花费时间,传送门增加时间,问是否存在道路能在同一个地点回到过去。

思路

裸的SPFA判断负环,如果存在负环,那么这条环路上的任何一个点都可以做到到达时间比出发时间早。

代码
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<iostream>
#include<cstring>
#include<queue>  
#define endl "\n"
using namespace std;
	typedef long long ll;
	const int maxn=550;
	const int maxe=8050;
	const int inf=0x3f3f3f3f;
	struct Edge{
		int v,w,next;
	}edge[maxe];
	int head[maxn],cnt;
	bool vis[maxn];//是否在队列 
	int in[maxn];//更新了多少次 
	int dis[maxn];
	int n,m,k;
	queue<int>q;
	
	void init(){
		memset(head,-1,sizeof(head));
		memset(vis,0,sizeof(vis));
		memset(in,0,sizeof(in));
		memset(dis,0x3f,sizeof(dis));
		cnt=0;
	}
	void add(int u,int v,int w){
		edge[cnt].v=v;
		edge[cnt].next=head[u];
		edge[cnt].w=w;
		head[u]=cnt;
		cnt++;
	}

	bool spfa(int s) {
		q.push(s);
		vis[s]=true;
		in[s]++;
		dis[s]=0;
		while(q.size()) {
			int p=q.front();q.pop();
			vis[p]=false;
			for(int i=head[p];i!=-1;i=edge[i].next) { //SPFA
				int v=edge[i].v;
				if(dis[v]>edge[i].w+dis[p]) {
					dis[v]=edge[i].w+dis[p];
					in[v]++;
					if(in[v]>=n)
						return true;//这个点更新了多于n次,说明存在负环 
					if(!vis[v]) {
						vis[v]=true;
						q.push(v);
					}
				}
			}
		}
		return false;
	}
	int main(){
		IOS
		int tn;
		cin>>tn;
		while(tn--){
			init();
			cin>>n>>m>>k;
			int u,v,w;
			while(m--){
				cin>>u>>v>>w;
				add(u,v,w);
				add(v,u,w);
			}
			while(k--){
				cin>>u>>v>>w;
				add(u,v,-w);//回溯w秒,所以是负 
			}
			if(spfa(1))
				cout<<"YES"<<endl;
			else
				cout<<"NO"<<endl;
		}
		
	} 
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值