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
USACO 2007 November Gold
|
题目: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; }