题目等价于判断图里面是否存在一个负环.首先可以采用bellman_ford算法,但是该算法需要一个起始点,而这里是需要判断整个图是否存在负环.因此可以假设有一个源点,假设它与其他所有点连通,并且花费都是0.这样就可以直接调用bellman_ford算法,如果原来的图存在负环,那么它一定也在新的源点所在的连通图里面.
#include "vector"
#include "iostream"
using namespace std;
const double inf = 10000000;
struct Edgestruct
{
int beg;
int end;
double time_cost;
};
typedef vector<Edgestruct> E;
typedef vector<double> D;
bool relax(Edgestruct & one_edge, D &distance)
{
if (distance[one_edge.beg] + one_edge.time_cost < distance[one_edge.end])
{
distance[one_edge.end] = distance[one_edge.beg] + one_edge.time_cost;
return true;
}
return false;
}
bool bellman_ford(E & edge, D & distance,int N)
{
for (size_t i = 1; i != N; ++i)
{
bool flag = false;
for (size_t j = 0; j != edge.size(); ++j)
{
if (relax(edge[j], distance)) flag = true;
}
if (distance[0] < 0) return true;
if (!flag) break;
}
for (size_t j = 0; j != edge.size();++j)
if (relax(edge[j], distance)) return true;
return false;
}
int main()
{
int F, N, M, W;
cin >> F;
while (F--)
{
cin >> N >> M >> W;
E edge;
int S, E;
double T;
while (M--)
{
cin >> S >> E >> T;
Edgestruct temp1 = { S, E, T };
edge.push_back(temp1);
Edgestruct temp2 = { E, S, T };
edge.push_back(temp2);
}
while (W--)
{
cin >> S >> E >> T;
Edgestruct temp = { S, E, -T };
edge.push_back(temp);
}
int count = N;
while (count--)
{
edge.push_back({0, count + 1, 0});
}
bool ispossible = false;
D distance(N+1,inf);
ispossible = bellman_ford(edge, distance, N);
if (ispossible)
cout << "YES" << endl;
else
cout << "NO"<<endl;
}
return 0;
}
Floyd:理论上可以,但是题目并不需要求出所有点的最短路径,用这个办法超时了.但是还是贴出来吧。
#include "vector"
#include "iostream"
using namespace std;
const double inf = 100000;
struct Edgestruct
{
int beg;
int end;
double time_cost;
};
double Distance[502][502] = {0};
typedef vector<Edgestruct> E;
bool relax(int beg,int end,int k)
{
if (Distance[beg][k] + Distance[k][end] < Distance[beg][end] )
{
Distance[beg][end] = Distance[beg][k] + Distance[k][end];
return true;
}
return false;
}
bool floyd(int N)
{
for (int m = 1; m != N + 1; ++m)
Distance[m][m] = 0;
bool flag = false;
for (size_t k = 1; k != N + 1;++k)
{
for (size_t i = 1; i != N + 1; ++i)
{
for (size_t j = 1; j != N + 1; ++j)
relax(i, j, k);
if (Distance[i][i] < 0)
return true;
}
}
return false;
}
int main()
{
int F, N, M, W;
cin >> F;
while (F--)
{
cin >> N >> M >> W;
for (size_t i = 1; i!=N+1; i++)
for (size_t j = 1; j!=N+1; j++)
Distance[i][j] = inf;
E edge;
int S, E;
double T;
while (M--)
{
cin >> S >> E >> T;
Distance[S][E] = T<Distance[S][E] ? T : Distance[S][E];
Distance[E][S] = T<Distance[E][S] ? T : Distance[E][S];
}
while (W--)
{
cin >> S >> E >> T;
Distance[S][E] = -T<Distance[S][E] ? -T:Distance[S][E];
}
bool ispossible = false;
ispossible = floyd(N);
if (ispossible)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}