Cow Relays
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 Output * Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly 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 Source |
题目:http://poj.org/problem?id=3613
题意:给你一张图,要你求出边数为n的一条从s到e的最短路。。。
分析:n比较大,一开始没什么想法,后来突然想到用一个矩阵表示点之间的转换关系,然后用矩阵连乘。。。虽然跟正解有点接近但是始终没反应过来= =
其实只要把矩阵的意思换成用了几条边后,点i到j的最短距离就行。。。每次矩阵相乘都是用floyd的方式来转移的。。。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef __int64 LL;
const int mm=1111;
const int mn=222;
const LL oo=1e15;
int id[mm];
LL ans[mn][mn],tmp[mn][mn],dis[mn][mn];
int n,T,m,s,t;
void prepare(LL a[mn][mn])
{
for(int i=0;i<mn;++i)
for(int j=0;j<mn;++j)
a[i][j]=oo;
}
void Multi(LL a[mn][mn],LL b[mn][mn])
{
int i,j,k;
prepare(tmp);
for(k=0;k<m;++k)
for(i=0;i<m;++i)
for(j=0;j<m;++j)
tmp[i][j]=min(tmp[i][j],a[i][k]+b[k][j]);
for(i=0;i<m;++i)
for(j=0;j<m;++j)
a[i][j]=tmp[i][j];
}
int main()
{
int i,j,k;
while(~scanf("%d%d%d%d",&n,&T,&s,&t))
{
prepare(dis),prepare(ans);
for(i=0;i<mn;++i)ans[i][i]=0;
m=0;
memset(id,-1,sizeof(id));
while(T--)
{
scanf("%d%d%d",&k,&i,&j);
i=id[i]<0?id[i]=m++:id[i];
j=id[j]<0?id[j]=m++:id[j];
dis[i][j]=dis[j][i]=min(dis[i][j],(LL)k);
}
while(n)
{
if(n&1)Multi(ans,dis);
Multi(dis,dis);
n>>=1;
}
printf("%I64d\n",ans[id[s]][id[t]]);
}
return 0;
}