[最短路] P3385 负环 题解

Date:2019/11/1

坑点

  1. 输出
  2. 板子的写法
  3. 数组要初始化!!!!!
    多组输入:数组不清零,爆零两行泪
  4. 每组数据建边的时候,tot|cnt要从0开始
    只有负数建单向边,0建双向边
  5. spfa的结尾要return false即为不是负环

AC code

#include<bits/stdc++.h>
using namespace std;
#define maxn 10000
int n,m,s,cnt;
int hd[maxn],		dis[2*maxn];
//hd[]--记边		dis[]--计最短路 
int vis[2*maxn],	ji[2*maxn];
//vis[]--标记数组   ji[]--记走了几步 
struct Edge{
	int to,nxt,w;
}edge[2*maxn];					//边的储存 
void add(int u,int v,int w){	//建边 
	cnt++;
	edge[cnt].to = v;
	edge[cnt].w = w; 
	edge[cnt].nxt = hd[u];
	hd[u] = cnt; 
}	
//----------------------------------------------------------							
bool spfa(){
	queue <int> q; 
	q.push(1); dis[1] =0;ji[1]=1;vis[1] = 1;
	while(!q.empty()){
		int u = q.front();		//取出队首 
		q.pop();				//弹出队首 
		vis[u] = false;			//队首还原(可以再次入队 
		for(int j = hd[u]; j!=-1;j = edge[j].nxt){//##这里不要写错!! 
			int v = edge[j].to;				//找儿子 
			if(dis[v] > dis[u] + edge[j].w){
				dis[v] = dis[u] + edge[j].w;//三角形的松弛操作 
				ji[v] = ji[u] + 1;		//入队次数记录 
				if(ji[v] > n){			//超了跳出 
					return true;
				}
				if(!vis[v]){			//如果没有遍历过 
					vis[v] = true;		//打标记 
					q.push(v);			//推入队列里 
				} 
			}
		}	
	}
	return false;//这里要注意~~ 
}
int main(){
//	freopen("1.in","r",stdin);
//	freopen("1.out","w",stdout);	//提交时候不要写这个!!! 
	int T;
	scanf("%d",&T);
	while(T--){
		cnt = 0;					//统计的数组初始化 
		scanf("%d %d",&n,&m);
		for(int i = 1;i <= n+5 ;i++){
			hd[i]=-1;				//建立边的数组初始化
			dis[i]=0x3f3f3f3f;		//距离数组初始化 (注意和 memset(dis,0x3f,sizeof(dis)) 的区别 
			vis[i]=0;				//标记数组初始化
			ji[i]=0;				//判定负环数组初始化
		}	
		for(int i = 1,fi,gi,wi; i <= m; i++){
			scanf("%d %d %d",&fi,&gi,&wi);
			add(fi,gi,wi);
			if(wi>=0)	add(gi,fi,wi);//这里是题目要求,双向 
		}
		
		if(spfa())	printf("YE5\n");
		else printf("N0\n");			//恶心心的输出 
	}
	return 0;
}


KaTeX parse error: Undefined control sequence: \font at position 16: \to \color{red}\̲f̲o̲n̲t̲{Happy \:ending

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值