您的位置:首页 > 其它

POJ3259 农场与虫洞 图论(Bellman-Ford求负环)

2014-12-29 14:23 429 查看
嗯图论的第二道题,刚刚有一点点入门的感觉www。

于是就把心得体会写下来啦。

题目概述:

主人公农夫有几片农场,然后农场里有各个农田(这个模型化为图的端点),然后各个农田之间有路径(这个模型化为图的边),然后有的边是正常的无向边,以及有的边是有项的虫洞。开始的时候时间为0,通过一条正常边会加时间,通过虫洞减去时间。

输入N(1-500),M(1-2500),W(1-100),然后输出能否通过一条路径回到过去,也就是模型中的负权环。

算法思想:

求负权显然的Bellman-Ford,可是还是太慢了要400多MS,不知道先进的方法是怎么样的。果然要看下SPFA么。。

大概跟标准模版无差,值得一提的是,这种算法求负权环有两种方式,第一种是求完最短路径然后继续检查更新,第二种是直接看更新能不能进行到第n-1次,两种代码我都实现了一遍,速度也并没有太大的差异。就列在下面了。

代码部分:

代码1:

#include <iostream>
using namespace std;
int N;int n,m,w;
int MAX = 21474836;

struct edge{
int from,to,cost;
};

int d[555];bool flag;
edge e[5600];

void init() {
flag = false;
cin >> n >> m >> w;
for (int i=0;i<n;i++){
d[i] = MAX;
}
d[0] = 0;
for (int i=0;i<2*m;i+=2){
int a,b,c;
cin >> a >> b >> c;
e[i].from = a;
e[i].to = b;
e[i].cost = c;
e[i+1].from = b;
e[i+1].to = a;
e[i+1].cost = c;
}
for (int i=2*m;i<2*m+w;i++){
int a,b,c;
cin >> a >> b >> c;
e[i].from = a;
e[i].to = b;
e[i].cost = c*(-1);
}
}

bool b_f() {
for (int i=0;i<n-1;i++){
for (int j=0;j<2*m+w;j++){
if (d[e[j].from] != MAX && d[e[j].to] > d[e[j].from]+e[j].cost) {
d[e[j].to] = d[e[j].from]+e[j].cost;
}
}
}

for (int j=0;j<2*m+w;j++){
if (d[e[j].to] > d[e[j].from]+e[j].cost) {
return true;
}
}
return false;

}

int main() {
cin >> N;
for (int k=0; k<N; ++k){
init();
if (b_f()) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}


代码2:

#include <iostream>
#include <string.h>
using namespace std;
int N;int n,m,w;

struct edge{
int from,to,cost;
};

int d[555];
edge e[5600];

void init() {
cin >> n >> m >> w;
memset(d,0,sizeof(d));
for (int i=0;i<m*2;i+=2){
int a,b,c;
cin >> a >> b >> c;
e[i].from = a;
e[i].to = b;
e[i].cost = c;
e[i+1].from = b;
e[i+1].to = a;
e[i+1].cost = c;
}
for (int i=2*m;i<2*m+w;i++){
int a,b,c;
cin >> a >> b >> c;
e[i].from = a;
e[i].to = b;
e[i].cost = c*(-1);
}
}

bool b_f() {
for (int i=0;i<n;i++){
for (int j=0;j<2*m+w;j++){
if (d[e[j].to] > d[e[j].from]+e[j].cost) {
d[e[j].to] = d[e[j].from]+e[j].cost;
if (i == n-1) return true;
}
}
}
return false;
}

int main() {
cin >> N;
for (int k=0; k<N; ++k){
init();
if (b_f()) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: