题目大意:农夫FJ喜欢在自己的农场里面玩穿越,而虫洞-----就是就是一种是时间倒退的时光机(单向的)(A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole!) 但是普通道路是双向的(a bidirectional path)。求判断会不会穿越成功看到从前的自己
思路1:因为顶点撑死500,边撑死5200,所以用Bellman-ford,最多执行次数是V*E=500*5200<300W,所以无压力。
思路2:用SPFA可以轻松撸过~~:http://blog.youkuaiyun.com/kg_second/article/details/8038440
program:
#include<iostream>
using namespace std;
#define INF 0x7FFFFFF
#define N 6000
struct E
{
int a,b,tm;
}e[N]; //用邻接表
int n,m,w,num;
void fi()
{
int a,b,tm;
num=1;
scanf("%d%d%d",&n,&m,&w);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&tm);
e[num].a=a; e[num].b=b; e[num].tm=tm;
num++;
e[num].b=a; e[num].a=b; e[num].tm=tm;
num++;
}
for(int i=1;i<=w;i++)
{
scanf("%d%d%d",&a,&b,&tm);
e[num].a=a; e[num].b=b; e[num].tm=(-1)*tm;
num++;
}
}
int bellman_frod()
{
int dis[N];
for(int i=1;i<=n;i++)
dis[i]=INF;
dis[1]=0;//以这个为源点
for(int i=1;i<n;i++)//松弛n-1次就必定找出最短路径了
{
for(int j=1;j<num;j++)
if(dis[e[j].b]>dis[e[j].a]+e[j].tm)
dis[e[j].b]= dis[e[j].a]+e[j].tm;
}
for(int j=1;j<num;j++)//再来一次判断有无负环
if(dis[e[j].b]>dis[e[j].a]+e[j].tm)
return 1;//注意哦~~1是表示有负环就是可以时空倒转
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
fi();
if(bellman_frod()==1)
printf("YES\n");
else
printf("NO\n");
}
system("pause");
return 0;}
总结:(1)判断负环的时候,就是前n-1次扫描已经找出最短路径,如果第
n次扫描还有边的值变化的话就说明有负环
(2)、在终点U变化的过程中,dis[]里面装的就是从加入1条、2条、3条边——到E条边的值的最小值