嗯图论的第二道题,刚刚有一点点入门的感觉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; }