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

来源:JZOJ #315

题目描述

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

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

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

给定图为连通图。

解题思路

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

代码君

#include 
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;
}

你可能感兴趣的:(#,图论-最短路,图论,图论,算法,c++)