SRM 626 D2L3:NegativeGraphDiv2,构造新图

来源:互联网 发布:php字符串拼接方法 编辑:程序博客网 时间:2024/06/10 03:13

题目:http://community.topcoder.com/stat?c=problem_statement&pm=13247

参考:http://apps.topcoder.com/wiki/display/tc/SRM+626

图中包含自环和负边,用普通方法很难求解,首先应该构造一个新的图,新图的节点表示为(k, v ),k表示还可以使用k次power,v表示当前节点位置。然后就是求(k, 1 ) 到 (0, N)的最短距离。由于存在负边,所以不能用Dijkstra算法,可以使用Bellman-Ford算法,但这种方法很慢,会超时,需要更快速的方法。使用Bellman-Ford算法的代码如下:

#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <iostream>#include <sstream>#include <iomanip>#include <bitset>#include <string>#include <vector>#include <stack>#include <deque>#include <queue>#include <set>#include <map>#include <cstdio>#include <cstdlib>#include <cctype>#include <cmath>#include <cstring>#include <ctime>#include <climits>using namespace std;#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)typedef pair<int, int> pii;typedef long long llong;typedef pair<llong, llong> pll;#define mkp make_pair/*************** Program Begin **********************/int dist[1001][51];int INF = 100000001;class NegativeGraphDiv2 {public:long long findMin(int N, vector <int> s, vector <int> t, vector <int> weight, int charges) {long long res = 0LL;int E = s.size();// Bellman–Ford algorithmfor (int i = 0; i <= charges; i++) {for (int j = 1; j <= N; j++) {dist[i][j] = INF;}dist[i][1] = 0;}for (int i = 0; i < (charges + 1) * N; i++) {for (int j = 0; j < E; j++) {int u = s[j], v = t[j], w = weight[j];for (int k = 0; k <= charges; k++) {if (dist[k][u] + w < dist[k][v]) {dist[k][v] = dist[k][u] + w;}if (k > 0 && dist[k][u] - w < dist[k-1][v]) {dist[k-1][v] = dist[k][u] - w;}}}}res = dist[0][N];for (int i = 0; i <= charges; i++) {res = min<int>(res, dist[i][N]);}return res;}};/************** Program End ************************/


通过观察新构造的图与原图的关系,可以发现一些特殊的性质,详细请看参考。实现代码如下:


代码:

#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <iostream>#include <sstream>#include <iomanip>#include <bitset>#include <string>#include <vector>#include <stack>#include <deque>#include <queue>#include <set>#include <map>#include <cstdio>#include <cstdlib>#include <cctype>#include <cmath>#include <cstring>#include <ctime>#include <climits>using namespace std;#define CHECKTIME() printf("%.2lf\n", (double)clock() / CLOCKS_PER_SEC)typedef pair<int, int> pii;typedef long long llong;typedef pair<llong, llong> pll;#define mkp make_pair/*************** Program Begin **********************/int dist[51][51];int xdist[1001][51];int INF = 100000001;class NegativeGraphDiv2 {public:long long findMin(int N, vector <int> s, vector <int> t, vector <int> weight, int charges) {long long res = 0LL;int E = s.size();for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {dist[i][j] = INF;}dist[i][i] = 0;}for (int i = 0; i < E; i++) {int u = s[i] - 1, v = t[i] - 1, w = weight[i];dist[u][v] = min(dist[u][v], w);}for (int k = 0; k < N; k++) {for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {dist[i][j] = min(dist[i][j], dist[i][k] +dist[k][j]);}}}for (int i = 0; i < N; i++) {xdist[0][i] = dist[i][N - 1];}for (int i = 1; i <= charges; i++) {for (int j = 0; j < N; j++) {xdist[i][j] = xdist[i - 1][j];for (int k = 0; k < E; k++) {int u = s[k] - 1, v = t[k] - 1, w = -weight[k];xdist[i][j] = min(xdist[i][j], dist[j][u] + w + xdist[i - 1][v]);}}}res = xdist[charges][0];return res;}};/************** Program End ************************/// Powered by FileEdit// Powered by CodeProcessor


1 0
原创粉丝点击