ACM: 经过K条边的最短路 图论题 po…
来源:互联网 发布:提花组织软件 编辑:程序博客网 时间:2024/06/03 19:59
For their physical fitness program, N (2 ≤ N ≤1,000,000) cows have decided to run a relay race using the T(2 ≤ T ≤ 100) cow trails throughout the pasture.
Each trail connects two different intersections (1 ≤I1i ≤ 1,000; 1 ≤I2i ≤ 1,000), each of which is thetermination for at least two trails. The cows know thelengthi of each trail (1 ≤lengthi
To run the relay, the N cows position themselves atvarious intersections (some intersections might have more than onecow). They must position themselves properly so that they can handoff the baton cow-by-cow and end up at the proper finishingplace.
Write a program to help position the cows. Find the shortestpath that connects the starting intersection (S) and theending intersection (E) and traverses exactly N cowtrails.
Input
* Line 1: Four space-separated integers: N, T,S, and E
* Lines 2..T+1: Line i+1 describes trail iwith three space-separated integers: lengthi ,I1i , and I2i
Output
* Line 1: A single integer that is the shortest distance fromintersection S to intersection E that traversesexactly N cow trails.
Sample Input
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
Sample Output
10
题意: 牛牛接力赛, 有一个无向图, 要你求出从start到end点的经过k条边的最短路.
解题思路: (WA了好多次, 是点映射的数组没有置零 T.T)
1. 我不知道是自己读错题意还是网上的人理解错了, 两个交叉路口不能有两个不同的trails
链接. 两个点之间是没有重边的.
2. 从i到j经过k条边的路是否有, 可以通过01临接矩阵幂次得出.
3. 但是题目是要求从i到j经过k条边的最短路.
问题分析:
我们不妨设dp[i][j][n]:表示从i到j经过n条边的最短路.
即:dp[i][j][n] = min(dp[i][k][t]+dp[k][j][n-t]);
讨论到这里, 我们妨思考怎么求出最短路问题. 显然floyd的DP思想.
在这里可以发现如果我们把dp[i][j][n] = min(dp[i][k][n/2]+dp[k][j][n/2]);
利用二分的思想+floyd问题就可以求解了.
4. 其实说白了就是, 第一次i->k 一条边, k->j 一条边 2
第二次i->k 两条边, k->j 两条边 4
......
第n次i->k 2^(n-1)条边, k->j 2^(n-1)条边 2^n
(奇数的情况可以用来单独求一次floyd直接路).
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAX 210
const int INF = (1<<30)-1;
int n, T, start, end;
int num, node[1005];
int g[MAX][MAX], result[MAX][MAX], temp[MAX][MAX];
void floyd(int c[][MAX], int a[][MAX], int b[][MAX])
{
for(int i = 1; i <= num; ++i)
for(int j = 1; j <= num; ++j)
c[i][j] = INF;
for(int k = 1; k <= num; ++k)
for(int i = 1; i <= num; ++i)
for(int j = 1; j <= num; ++j)
if(c[i][j] > a[i][k]+b[k][j])
c[i][j] = a[i][k]+b[k][j];
for(int i = 1; i <= num; ++i)
for(int j = 1; j <= num; ++j)
a[i][j] = c[i][j];
}
void solve(int n)
{
while(n)
{
if(n % 2 == 1)