题目链接:http://poj.org/problem?id=3259
题意:从给出的点中任意一个点出发,如果存在一个点能在出发过后回到原点并且所花时间小于0的话就输出YES,否则NO;
一开始看错题目了,以为是从第一个点1出发能不能回到原点(如果英文题不用谷歌翻译,战斗力减半 XD)
Bellman 和Folyd应该都是可以的,我们换一种问法会比较好解题,如果任意一点出发都不能在所花时间小于0的情况下回到原点,就输出NO,那么解法就是判断有没有负环,如果否命题比较容易解就选择否命题的方式写代码;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int Maxn = 510;
const int Maxm = 50210;
const int INF = 0x3f3f3f3f;
struct Edge {
int u,v,w;
} edges[Maxm];
int d[Maxn],E,V,M,worm;
void solve () {
for (int i = 1; i <= V; ++i) d[i] = INF;
d[1] = 0; bool check,ok = false;;
for (int i = 1; i <= V; ++i) {
for (int j = 1; j <= E; ++j) {
Edge &e = edges[j];
if(d[e.u] != INF && d[e.v] > d[e.u]+e.w) {
if(i == V) ok = true; // 第V次还能松弛说明有负环
d[e.v] = d[e.u]+e.w;
check = true; // 一个小剪枝,如果在V-1之前就没有能松弛的边就直接退出;
}
}
if(!check) break;
}
if(ok) printf("YES\n");
else printf("NO\n");
}
int main (void)
{
int t,u,v,w;
scanf("%d",&t);
while (t--) {
scanf("%d%d%d",&V,&M,&worm);
E = 0;
for (int i = 1; i <= M; ++i) {
scanf("%d%d%d",&u,&v,&w);
edges[++E].u = u;
edges[E].v = v; edges[E].w = w;
edges[++E].u = v;
edges[E].v = u; edges[E].w = w;
}
for (int i = 1; i <= worm; ++i) {
scanf("%d%d%d",&u,&v,&w);
edges[++E].u = u;
edges[E].v = v;
edges[E].w = (-1)*w;
}
solve ();
}
return 0;
}