题目大意:FJ有F个农场,每个农场有N块田地,M条双向路径,W个虫洞,虫洞能让你单向返回到某个时间之前,问FJ能不能从某块田地出发,经过若干田地和虫洞后回到原点遇到出发前的自己
输入:F (1 ≤ F ≤ 5)
N M W (1 ≤ N ≤ 500) (1 ≤ M ≤ 2500) (1 ≤ W ≤ 200)
S E T(SE之间经过T秒有条路,共M行表示M条双向路)
S E T(S到E有个虫洞,退回T秒,共W行表示W条路)(时间均不超过10000s)
输出:YES/NO
分析:bellman-ford算法或者spfa都可以。本题就是找是否存在负权回路。
代码:转载自http://blog.youkuaiyun.com/sky1203850702/article/details/7868305
#include <iostream>
#include <cstdio>
#define inf 1000000
using namespace std;
const int maxn=502;
const int maxm=5210;
int n,m,w,num,dist[maxn];
struct Edge
{
int u; //边的起点
int v; //边的终点
int w;
}edge[maxm];
bool Bellman_Ford()
{
int i,j;
bool flag;
dist[1]=0;
for(i=1;i<n;i++)
{
flag=false;
for(j=0;j<num;j++)
if(dist[edge[j].u]+edge[j].w<dist[edge[j].v])
{
dist[edge[j].v]=dist[edge[j].u]+edge[j].w;
flag=true;
}
if(!flag) //不存在负权环
return false;
}
for(i=0;i<num;i++)
if(dist[edge[i].u]+edge[i].w<dist[edge[i].v])
return true; //经过n-1次的松弛操作后还能更新,说明存在负权环
}
int main()
{
int i,j,f,s,e,t;
scanf("%d",&f);
while(f--)
{
scanf("%d%d%d",&n,&m,&w);
num=0;
for(i=0;i<m;i++) //普通路径,双向边
{
scanf("%d%d%d",&s,&e,&t);
edge[num].u=s;
edge[num].v=e;
edge[num++].w=t;
edge[num].u=e;
edge[num].v=s;
edge[num++].w=t;
}
for(i=0;i<w;i++)
{
scanf("%d%d%d",&s,&e,&t);
edge[num].u=s;
edge[num].v=e;
edge[num++].w=-t;
}
for(i=1;i<=n;i++)
dist[i]=inf;
if(Bellman_Ford())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}