题目大意: 约翰有N个农场, 农场之间有M条路 和 W 个虫洞, 其中路是双向的, 话费时间t, 而虫洞花费的时间是负的, 而且是单向的. 问, 约翰能不能从一个农场出发, 通过这些虫洞和路回到这个农场, 而且时间在这个时间之前.
题目分析: 很明显是找负圈的裸题, 农场做顶点, 路和虫洞做边建图, 其中虫洞的边权重是负的即可. 用Bellman-Ford算法找有没有负圈即可.
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 1e5;
const int MAXN = 505;
int d[MAXN];
int maxE;
struct edge
{
int fo, to;
int t;
}E[5550];
bool Bellman_Ford(int maxV)
{
memset(d, 0, sizeof d);
for(int i=0; i<maxV; ++i)
{
bool update = false;
for(int j=0; j<maxE; ++j)
{
edge e = E[j];
if(d[e.fo] + e.t < d[e.to])
{
update = true;
d[e.to] = d[e.fo] + e.t;
}
}
if(!update) break;
if(i == maxV-1) return true;
}
return false;
}
int main()
{
int T, n, m, w;
int s, e, t;
cin >>T;
while(T--)
{
scanf("%d%d%d", &n, &m, &w);
for(int i=0; i<m; ++i)
{
scanf("%d%d%d", &s, &e, &t);
E[i] = (edge){s, e, t};
E[i+m] = (edge){e, s, t};
}
for(int i=0; i<w; ++i)
{
scanf("%d%d%d", &s, &e, &t);
E[i+m*2] = (edge){s, e, -t};
}
maxE = m*2+w;
if(Bellman_Ford(n)) printf("YES\n");
else printf("NO\n");
}
return 0;
}