一.原题链接:http://poj.org/problem?id=3259
二.题目大意:从一个田地开始可以花Ts到另一田地,并且回来是同一时间。(双向边)田地之间有虫洞,单向边,走过虫洞可以使时间倒流。问能不能从某一个田地出发,回到改田地使得时光倒流。
三.思路:就是判断有没有负环,有的话就YES,否则NO。
四.AC代码:
spfa:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int MAX_SIZE = 520,
INF = 1<<29,
MOD = 1000000007;
int graph[MAX_SIZE][MAX_SIZE];
//PedgeNum 表示正边数,NedgeNum表示负边数
int nodeNum, PedgeNum, NedgeNum;
void initGraph()
{
int i, j;
for(i = 0; i < MAX_SIZE; i++)
for(j = 0; j < MAX_SIZE; j++)
graph[i][j] = INF;
}
//有负环返回 false, 否则返回 true
bool spfa()
{
int dist[MAX_SIZE], cnt[MAX_SIZE] = {0}, i, j, cur;
bool inQue[MAX_SIZE] = {0};
queue <int> que;
//设0为起点
for(i = 1; i <= nodeNum; i++)
dist[i] = (1 == i? 0:INF);
que.push(1);
inQue[1] = true;
cnt[1]++;
while(!que.empty()){
cur = que.front();
inQue[cur] = false;
que.pop();
for(i = 1; i <= nodeNum; i++){
if(dist[i] > dist[cur] + graph[cur][i]){
dist[i] = dist[cur] + graph[cur][i];
if(cnt[i] > nodeNum-1)
return false;
if(!inQue[i]){
que.push(i);
inQue[i] = true;
cnt[i]++;
}
}
}
}
return true;
}
int main()
{
//freopen("in.txt", "r", stdin);
int test, i, j, S, E, weight;
cin>>test;
while(test--){
cin>>nodeNum>>PedgeNum>>NedgeNum;
initGraph();
for(i = 0; i < PedgeNum; i++){
cin>>S>>E>>weight;
if(graph[S][E] > weight){
graph[S][E] = weight;
graph[E][S] = weight;
}
}
for(i = 0; i < NedgeNum; i++){
cin>>S>>E>>weight;
graph[S][E] = -weight;
}
if(spfa())
cout<<"NO\n";
else
cout<<"YES\n";
}
}
bellman_Ford:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int MAX_SIZE = 520,
INF = 1<<29,
MOD = 1000000007;
//PedgeNum 表示正边数,NedgeNum表示负边数
int nodeNum, PedgeNum, NedgeNum, edgeNum;
struct Edge
{
int S, E, weight;
};
Edge edge[MAX_SIZE*MAX_SIZE];
//有负环返回 false, 否则返回 true
bool bellman_Ford()
{
int dist[MAX_SIZE], i, j, flag;
for(i = 1; i <= nodeNum; i++)
dist[i] = (1 == i? 0:INF);
for(i = 1; i < nodeNum; i++){
flag = false;
for(j = 0; j < edgeNum; j++)
if(dist[edge[j].E] > dist[edge[j].S] + edge[j].weight){
dist[edge[j].E] = dist[edge[j].S] + edge[j].weight;
flag = true;
}
if(!flag)
return true;
//正常情况下这里只是 break 但是这里只要判断负环,可直接返回
}
for(j = 0; j < edgeNum; j++)
if(dist[edge[j].E] > dist[edge[j].S] + edge[j].weight)
return false;
return true;
}
int main()
{
//freopen("in.txt", "r", stdin);
int test, i, j, S, E, weight;
cin>>test;
while(test--){
cin>>nodeNum>>PedgeNum>>NedgeNum;
edgeNum = 0;
for(i = 0; i < PedgeNum; i++){
cin>>S>>E>>weight;
edge[edgeNum].S = edge[edgeNum + 1].E = S;
edge[edgeNum].E = edge[edgeNum + 1].S = E;
edge[edgeNum].weight = edge[edgeNum + 1].weight = weight;
edgeNum += 2;
}
for(i = 0; i < NedgeNum; i++){
cin>>S>>E>>weight;
edge[edgeNum].S = S;
edge[edgeNum].E = E;
edge[edgeNum].weight = - weight;
edgeNum++;
}
if(bellman_Ford())
cout<<"NO\n";
else
cout<<"YES\n";
}
}