路径数限制的最短路径 POJ 3613

http://poj.org/problem?id=3613

/* 题意就是用N条边的最短路,采用的是Flody算法+倍增法莱求解 dp[i][j][k]表示从节点i到节点j经过k条边的最短路: dp[i][j][k] = max {dp[i][j][k], dp[i][t][k/2] + dp[t][j][(k+1)/2]} 求解时采用倍增法才可以通过:其中先求出f[i][j][1],再求出f[i][j][2]。。。。再求f[i][j][k],在求f[i][j][2*k],f[i][j][2*k+1] 对n采用二进制表示后可根据串来决定求出f[i][j][k]后再求f[i][j][2*k]还是求f[i][j][2*k+1] */ #include<iostream> #include<vector> using namespace std; const int inf = INT_MAX/2; const int MAXN = 1001; int map[MAXN][MAXN];//用来储存图的结构 vector<int> ver; bool used[MAXN];//用来标记是否在向量中 bool mk[MAXN]; int minv, maxv;//用来标记 int next[MAXN][MAXN], ans[MAXN][MAXN]; int dis[MAXN][MAXN]; int min(int a, int b, int c) { int d = inf; d = d > a ? a : d; d = d > b ? b : d; d = d > c ? c : d; return d; } int max(int a, int b, int c) { int d = -1; d = d > a ? d : a; d = d > b ? d : b; d = d > c ? d : c; return d; } void flody(int dis[][MAXN], int map[][MAXN], int ans[][MAXN]) { int i, j, k, s, e, tv; for(i=0; i<ver.size(); i++) for(j=0; j<ver.size(); j++) for(k=0; k<ver.size(); k++) { tv = ver[i]; s = ver[j]; e = ver[k]; if(dis[s][e] > map[s][tv] + ans[tv][e]) dis[s][e] = dis[e][s] = map[s][tv] + ans[tv][e]; } } void c_copy(int a[][MAXN], int b[][MAXN]) { int i, j, s, e; for(i=0; i<ver.size(); i++) for(j=0; j<ver.size(); j++) { s = ver[i]; e = ver[j]; a[s][e] = b[s][e]; b[s][e] = inf; } } void solve(int n) { int i, j, s, e; int t; int flag[32]; for(i=0; i<ver.size(); i++)// 初始化 { for(j=0; j<ver.size(); j++) { s = ver[i]; e = ver[j]; dis[s][e] = ans[s][e] = next[s][e] = inf; } ans[ver[i]][ver[i]] = 0; } t = 0; while(n)//将n转换成二进制数 { if(n%2)//奇数 { flag[t++] = 1; } else flag[t++] = 0; n /= 2; } for(i=t-1; i>=0; i--) { flody(next, ans, ans); c_copy(ans, next); if(flag[i]) { flody(next, ans, map); c_copy(ans, next); } } } int main() { // freopen("in.txt","r",stdin); int N, T, S, E; int a, b, i, j, c; while(scanf("%d %d %d %d", &N, &T, &S, &E) != EOF) { minv = inf, maxv = -1; memset(used, 0, sizeof(used)); ver.clear(); for(i=1; i<MAXN; i++) for(j=1; j<MAXN; j++) map[i][j] = inf; used[S] = 1; ver.push_back(S); minv = min(minv, S, E); maxv = max(maxv, S, E); if(!used[E]) { used[E] = 1; ver.push_back(E); } while(T--) { scanf("%d%d%d", &a, &b, &c); map[b][c] = map[b][c] > a ? a : map[b][c]; map[c][b] = map[b][c]; if(!used[c]) { used[c] = 1; ver.push_back(c); } if(!used[b]) { used[b] = 1; ver.push_back(b); } minv = min(minv, b, c); maxv = max(maxv, b, c); } solve(N); printf("%d/n", ans[S][E]); } return 0; }

你可能感兴趣的:(路径数限制的最短路径 POJ 3613)