Description
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 the termination for at least two
trails. The cows know the lengthi of each trail (1 ≤ lengthi ≤
1,000), the two intersections the trail connects, and they know that
no two intersections are directly connected by two different trails.
The trails form a structure known mathematically as a graph.To run the relay, the N cows position themselves at various
intersections (some intersections might have more than one cow). They
must position themselves properly so that they can hand off the baton
cow-by-cow and end up at the proper finishing place.Write a program to help position the cows. Find the shortest path that
connects the starting intersection (S) and the ending intersection (E)
and traverses exactly N cow trails.Input
- Line 1: Four space-separated integers: N, T, S, and E
- Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: lengthi , I1i , and I2i
Output
- Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.
为了方便,题目里面、题解里面和代码里面的字母可能不一样。
很容易想到动态规划,dp[i][j][k]表示i到j走k条路的最短路。
dp[i][j][k]=min(dp[i][l][k-1]+len(l,j))。
但是因为k很大,复杂度O(n^3*k) 会超。
于是考虑按k倍增。
dp[i][j][k]表示从i到j,走2^k步的最短路。
dp[i][j][k]=min(dp[i][l][k-1]+dp[l][j][k-1])。
复杂度降为O(n^3*logk)。
最后求解的时候,仿照快速幂的思想,枚举每一位。
dis[q][i]=min(dis[q-1][j]+dp[j][i][k])。
所以其实连图都不用存。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
int dp[110][110][22],dis[22][210];
map<int,int> mp;
int main()
{
int i,j,k,m,n,p,q,x,y,z,s,t,lim,l;
n=0;
scanf("%d%d%d%d",&p,&m,&s,&t);
memset(dp,0x3f,sizeof(dp));
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&z,&x,&y);
if (!mp.count(x)) mp[x]=++n;
if (!mp.count(y)) mp[y]=++n;
dp[mp[x]][mp[y]][0]=dp[mp[y]][mp[x]][0]=z;
}
lim=log(p+0.5)/log(2);
for (k=1;k<=lim;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
for (l=1;l<=n;l++)
dp[i][j][k]=min(dp[i][j][k],dp[i][l][k-1]+dp[l][j][k-1]);
memset(dis,0x3f,sizeof(dis));
dis[0][mp[s]]=0;
q=0;
for (k=0;k<=lim;k++)
if (p&(1<<k))
{
q++;
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
dis[q][i]=min(dis[q][i],dis[q-1][j]+dp[j][i][k]);
}
printf("%d\n",dis[q][mp[t]]);
}