USACO 虫洞
2017年6月21日
Bellman-Ford 算法
#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
using namespace std;
/*
有N(1 <= N <= 500)个洞口,标号1..N;
它们之间有M (1 <= M <= 2500)条通道相连;
有W (1 <= W <=200)条时间虫洞;
INPUT
第一行:一个整数 F (1 <= F <= 5),表示共有F组数据。(多组数据测试)
每组数据:
第1行:三个整数 N M W
第2至M+1行:每行三个整数 (S, E, T),表示在S与E洞口之间有一个双向通道,通过需要T(0 <= T <= 10,000) 秒。
第M+2至M+W+1行:每行三个整数 (S, E, T),表示在S与E洞口之间有一个单向通道,从S到E可以回到之前T(0 <= T <= 10,000) 秒。
*/
int F;
int N, M, W;
int sr, en, ti;
struct Edges{
int x, y, v;
}E[6000];
int ans_egs;
int V_dis[510];
inline void ReadInEgde(int m, int n, int p){
E[++ans_egs].x = m;
E[ans_egs].y = n;
E[ans_egs].v = p;
}
void Putin()
{
cin >> N >> M >> W;
for(int i = 1; i <= M; i++){
cin >> sr >> en >> ti;
ReadInEgde(sr, en, ti);
ReadInEgde(en, sr, ti);
}
for(int i = 1; i <= W; i++){
cin >> sr >> en >> ti;
ReadInEgde(sr, en, -ti);
}
}
bool SP_BELLMANFORD()
{
V_dis[1] = 0; bool Rel;
for(int k = 1; k <= N; k++)
{
Rel = false;
for(int i = 1; i <= ans_egs; i++)
if(V_dis[E[i].x] + E[i].v < V_dis[E[i].y]){
Rel = true;
V_dis[E[i].y] = V_dis[E[i].x] + E[i].v;
}
if(!Rel) return false;
}
return true;
}
int main()
{
cin >> F;
for(int i = 1; i <= F; i++){
memset(V_dis, 10, sizeof(V_dis));
ans_egs = 0;
Putin();
bool jud = SP_BELLMANFORD();
if(!jud) cout << "NO" << endl;
else cout << "YES" << endl;
//return 0;//DEBUGS
}
return 0;
}