过年了,写点水题熟练算法的使用,开心开心。
题意:某人农场里有N个点,M条边,W个虫洞。边将点相连。走到虫洞需要花费时间,但是穿梭虫洞你会穿越到以前的时空。问他能在起点看见自己的身影吗?
用bellman-ford判负权回路。
#include <cstdio>
#include <cstring>
#include <vector>
#define DEB puts("debug")
#define F(_i,_u) for(int _i=0;_i<(_u);_i++)
#define TRV(_i,_V) for(int _i=(_V).size()-1;_i+1;_i--)
#define PB push_back
#define all(x) x.begin(),x.end()
using namespace std;
//边结构体
struct e{
int u,v,w;
//边构造器
e(){}
e(int _u,int _v,int _w){
u=_u;v=_v;w=_w;
}
};
//边集
vector<e> E;
//最短路
double dist[105]={0};
int main(){
//t 总case数
//N,M,W题目中有介绍
//a,b,:边的端点,v:边权
int t,N,M,W,a,b,v;bool released;
for(scanf("%d",&t);t--;){
scanf("%d%d%d",&N,&M,&W);
//初始化dist为INF,dist[1]为0
memset(dist,0x3f,sizeof(dist));
dist[1]=0;
E.clear();
F(m,M){
scanf("%d%d%d",&a,&b,&v);
//无向图转化为有向图
E.PB(e(a,b,v));
E.PB(e(b,a,v));
}
//虫洞是负权
F(w,W){
scanf("%d%d%d",&a,&b,&v);
E.PB(e(a,b,-v));
}
F(i,N){
released=false;
TRV(j,E){
if(dist[E[j].v]>dist[E[j].u]+E[j].w){
dist[E[j].v]=dist[E[j].u]+E[j].w;
released=true;
}
}
if(!released)break;
}
//判环
released=false;
TRV(j,E){
//一旦松弛更新次数就>=n次
if(dist[E[j].v]>dist[E[j].u]+E[j].w){
released=true;
break;
}
}
puts(released?"YES":"NO");
}
}