POJ3259 農場與蟲洞 圖論(Bellman-Ford求負環)
阿新 • • 發佈:2019-02-19
嗯圖論的第二道題,剛剛有一點點入門的感覺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; }