来源:JZOJ #315
题目描述
在一个神秘岛上,有 个洞口,标号 ,它们之间有 条通道相连。
神秘的竟然另外还有 条传说中的时间虫洞----当到达通道的另一端洞口时,竟然可以比进入的时间要早!
你当然想进行这样的时间之旅,希望从一个洞口 出发,经过几个通道,在比出发早些时候的时间回到洞口s。也许还能碰到自己呢,hehe 根据给定的地图,请判断能否实现这样的愿望。
给定图为连通图。
解题思路
- 这是一道 的板子题,这里为了练 ,我采用这种算法;
- 用边集数组(边表)存储图,在 中判断,若有负环输出 ,否则输出
代码君
#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;
}