UVA - 558 Wormholes (Bellman-ford)

来源:互联网 发布:linux 网页中文乱码 编辑:程序博客网 时间:2024/04/30 07:39
题目大意:
在公元2163年,人类发现了虫洞,虫洞是连接时间和两个星系的隧道。
于是就有些疯狂的科学家题意,要穿越到时间的尽头,看宇宙大爆炸。
现在给你n个点和m条边,没条边都有两个端点和一个权值。
如果权值 > 0,就表示这个虫洞,能穿越到未来。
权值 < 0,就表示这个虫洞,能穿越到从前。
现在问你科学家能否穿越到时间的尽头,看宇宙大爆炸。

解析:
最近很流行的电影《时空穿越》,讲的就是人类从一个星系穿越到另一个星系。

能否无限穿越到从前,就是问是否存在一个负环。这里可以用Bellman_ford算法来判断。

Bellman_ford算法模板:

前面先遍历n-1是代表最坏的情况是遍历n-1,求出最优的解,继续第n次操作,最优解应当和第n-1次操作相同,如果不同,那么就是存在负环。

bool bellman_ford(int s) {for(int i = 0; i < n; i++) {d[i] = INF;}d[s] = 0;int x ,y;for(int k = 0; k < n-1; k++) { //迭代n-1次for(int i = 0; i < m; i++) { //检查每条边x = u[i], y = v[i];if(d[x] < INF) {d[y] = min(d[y], d[x] + w[i]);}}}for(int i = 0; i < m; i++) {x = u[i] , y = v[i];int tmp = d[y];d[y] = min(d[y], d[x] + w[i]);if(d[y] != tmp) {return false;}}return true;}

AC代码:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 2005;const int INF = 0x3f3f3f3f;int u[maxn],v[maxn],w[maxn];int d[maxn];int n,m;bool bellman_ford(int s) {for(int i = 0; i < n; i++) {d[i] = INF;}d[s] = 0;int x ,y;for(int k = 0; k < n-1; k++) { //迭代n-1次for(int i = 0; i < m; i++) { //检查每条边x = u[i], y = v[i];if(d[x] < INF) {d[y] = min(d[y], d[x] + w[i]);}}}for(int i = 0; i < m; i++) {x = u[i] , y = v[i];int tmp = d[y];d[y] = min(d[y], d[x] + w[i]);if(d[y] != tmp) {return false;}}return true;}int main() {int T;scanf("%d",&T);while(T--) {scanf("%d%d",&n,&m);for(int i = 0; i < m; i++) {scanf("%d%d%d",&u[i],&v[i],&w[i]);}int ok = bellman_ford(0);if(ok) {printf("not possible\n");}else {printf("possible\n");}}return 0;}

用邻接表的方法:

#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 1005;struct Edge {int from ,to ,dist;Edge(int u,int v,int d) {from = u;to = v;dist = d;}};struct Bellman {int n,m;vector<Edge> edges;vector<int> G[maxn];bool done[maxn];int d[maxn];int p[maxn];int inq[maxn],cnt[maxn];void init(int n) {this->n = n;for(int i = 0; i < n; i++) {G[i].clear();}edges.clear();}void addEdge(int from,int to,int dist) {edges.push_back(Edge(from, to, dist));m = edges.size();G[from].push_back(m-1);}bool bellman_ford(int s) {queue<int> Q;memset(inq,0,sizeof(inq));memset(cnt,0,sizeof(cnt));for(int i = 0; i < n; i++) {d[i] = INF;}d[s] = 0;inq[s] = true;Q.push(s);while(!Q.empty()) {int u = Q.front();Q.pop();inq[u] = false;for(int i = 0; i < G[u].size(); i++) {Edge& e = edges[G[u][i]];if(d[u] < INF && d[e.to] > d[u] + e.dist) {d[e.to] = d[u] + e.dist;p[e.to] = G[u][i];if(!inq[e.to]) {Q.push(e.to);inq[e.to] = true;if(++cnt[e.to] > n) {return false;}}}}}return true;}};int main() {Bellman bell;int T;int n,m;int u,v,dist;scanf("%d",&T);while(T--) {scanf("%d%d",&n,&m);bell.init(n);for(int i = 0; i < m; i++) {scanf("%d%d%d",&u,&v,&dist);bell.addEdge(u,v,dist);}int ok = bell.bellman_ford(0);if(!ok) {printf("possible\n");}else {printf("not possible\n");}}return 0;}


0 0
原创粉丝点击