一、BellmanFord算法
参考我之前一篇博文:http://www.cnblogs.com/Oloo/articles/3612366.html
或者《算法导论》第24章单源最短路 bellmanford部分
二、问题描述
POJ 3259:http://poj.org/problem?id=3259
有F个农庄。
对于每个农庄有N块田,有M条路分别连接两块田,这M条路是双向的<第一次没注意到这个条件,导致WA了一次>,有W个虫洞,每个虫洞连接两块田,但是是单向的。
对于每个农场判断,存不存在一个点,从该点出发,经过虫洞和一系列路径可以回到该点,看到以前的出发时候的自己。
三、问题分析
编程之前需要解决两个问题:
问题一、图的构造
问题二、目标转换
问题一:这道题目图的构造还是很简单的!以每块田为节点,每条路<包括虫洞>作为边,这样这个图就构造起来了。
问题二:图构造好之后,我们很容易发现,这个问题的就是要我们判断图中是否存在负圈,一提到判断图中是否存在负圈,第一时间就可以想到BellmanFord算法。
四、程序实现
1 #include<iostream> 2 using namespace std; 3 4 struct edge 5 { 6 int u,v; 7 int value; 8 } *edges; 9 int N; //节点数目 10 int M;//普通边数 11 int W;//虫洞边数 12 int *value;//节点d值 13 14 void input() 15 { 16 cin>>N>>M>>W; 17 value = new int[(N+1)]; 18 for(int i = 0;i < N+1;i++) 19 value[i] = 10001; 20 value[1] = 0; 21 edges = new edge[(2*M+W)]; 22 for(int i = 0;i < 2*M;i++) 23 { 24 cin>>edges[i].u>>edges[i].v>>edges[i].value; 25 edges[i+1].u = edges[i].v; 26 edges[i+1].v = edges[i].u; 27 edges[i+1].value = edges[i].value; 28 i++; 29 } 30 for(int i = 2*M;i < W+2*M;i++) 31 { 32 int d = 0; 33 cin>>edges[i].u>>edges[i].v; 34 cin >> d; 35 edges[i].value = -d; 36 } 37 } 38 39 int Relax(int i) 40 { 41 if(value[edges[i].v] > value[edges[i].u]+edges[i].value) 42 { 43 value[edges[i].v] = value[edges[i].u]+edges[i].value; 44 return 1; 45 } 46 return 0; 47 } 48 49 int BellmanFord() 50 { 51 int k = 0; 52 while(k < N) 53 { 54 int flag = 0; 55 for(int i = 0;i < 2*M+W;i++) 56 if(Relax(i)) 57 flag = 1; 58 if(!flag) break; 59 k++; 60 } 61 for(int i = 0;i < 2*M+W;i++) 62 if(value[edges[i].v] > value[edges[i].u]+edges[i].value) 63 return 1; 64 return 0; 65 } 66 67 int main() 68 { 69 int F = 0;//农场数量 70 cin >> F; 71 while(F--) 72 { 73 input(); 74 if(BellmanFord()) cout << "YES" <<endl; 75 else cout <<"NO"<<endl; 76 } 77 return 0; 78 }
五、感想
自己通过自己独立分析问题,自己独立编程实现,最后这个题目AC,这个节奏还是很好的~
最后,YZY,我想你!~
浙公网安备 33010602011771号