JZOJ #315 虫洞-wormhole(图论-Bellman-ford)

来源:JZOJ #315

题目描述

在一个神秘岛上,有 N ( 1 < = N < = 500 ) N(1 <= N <= 500) 个洞口,标号 1.. N 1..N ,它们之间有 M ( 1 < = M < = 2500 ) M (1 <= M <= 2500) 条通道相连。

神秘的竟然另外还有 W ( 1 < = W < = 200 ) W (1 <= W <=200) 条传说中的时间虫洞----当到达通道的另一端洞口时,竟然可以比进入的时间要早!

你当然想进行这样的时间之旅,希望从一个洞口 s s 出发,经过几个通道,在比出发早些时候的时间回到洞口s。也许还能碰到自己呢,hehe 根据给定的地图,请判断能否实现这样的愿望。

给定图为连通图。

解题思路

  • 这是一道 B e l l m a n f o r d / S P F A Bellman-ford/SPFA 的板子题,这里为了练 B e l l m a n f o r d Bellman-ford ,我采用这种算法;
  • 用边集数组(边表)存储图,在 S P F A SPFA 中判断,若有负环输出 Y E S “YES” ,否则输出 N O “NO”

代码君

#include <bits/stdc++.h>
using namespace std;
int F,tot=0,n,m,w;
int dis[100005];
struct node
{
	int x,y,v;
}a[100005];
int bellman_ford()  //板子
{
	memset(dis,10,sizeof(dis));  //初值
	dis[1]=0;  //起点到起点的距离为0
	for (int i=1;i<=n;i++)  //最多迭代n次
	{
		bool p=0;  //是否有松弛标记
		for (int j=1;j<=tot;j++)  //tot条边
		{
			int ax=a[j].x,ay=a[j].y,av=a[j].v;  //第j条边起点,终点,长度
			if (dis[ax]+av<dis[ay])  //三角形迭代
			{
				dis[ay]=dis[ax]+av;
				p=1;  //松弛标记
			}
		}
		if (p==0) return 0;  //无松弛
	}
	return 1;  //有负环
}
void init()
{
	scanf("%d %d %d",&n,&m,&w);
	tot=0;
	for (int i=1;i<=m;i++)
	{
		int xx,yy,vv;
		scanf("%d %d %d",&xx,&yy,&vv);
		a[++tot].x=xx;  //边表
		a[tot].y=yy;
		a[tot].v=vv;
		a[++tot].x=yy;  //双向
		a[tot].y=xx;
		a[tot].v=vv;
	}
	for (int i=1;i<=w;i++)
	{
		int xx,yy,vv;
		scanf("%d %d %d",&xx,&yy,&vv);  //单向
		a[++tot].x=xx;
		a[tot].y=yy;
		a[tot].v=-vv;
	}
}
int main()
{
	freopen("wormhole.in","r",stdin);
	freopen("wormhole.out","w",stdout);
	scanf("%d",&F);
	for (int i=1;i<=F;i++)
	{
		init();
		if (bellman_ford()==1) printf("YES\n");  //判断
		 else printf("NO\n");
	}
	return 0;
}
发布了27 篇原创文章 · 获赞 33 · 访问量 1693

猜你喜欢

转载自blog.csdn.net/qq_43081996/article/details/104151956
315