poj3613:Cow Relays(倍增優化+矩陣乘法floyd+快速冪)
Cow Relays
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 7825 | Accepted: 3068 |
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 ≤ I
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
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.
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
題意
給出一張圖,求k邊最短路,即經過k條邊的最短路。
分析
思考一下:如果一個矩陣,表示走k條邊後,一張圖的點與點的最短路徑,(a,b)表示從a到b的最短路徑,然後我們把它與自己,按照矩陣乘法的格式“相乘”,把其中的乘改為取min,c.a[i][j] = min(c.a[i][j],x.a[i][k]+y.a[k][j]);看不懂先看下面。
這樣得到的是走k+k條邊的矩陣。有點抽象,下面詳細解釋下:
c中的一個點(a,b),當我們用a矩陣和b矩陣求它時,我們枚舉了x矩陣的a行所有數,與y矩陣的b列所有數,並且他們的坐標只能是相對應的,比如x矩陣的(a,2)這個點,相應的y矩陣點就是(2,b),那麽放到圖上去理解,即從a點經過2點到b點的距離,類似的點不只有2,把所有點枚舉完後,c.a[a][b]就是從a到b的最短距離。(意會一下)
這樣下來,會得到走k+k條邊的最短路徑,對於其他的矩陣這樣操作,得到的是他們兩個,經過的邊數相加的結果。(一個經過a條邊後的矩陣 與 一個經過b條邊後的矩陣這樣操作後,是經過a+b條邊後的矩陣,矩陣中存的是最短路徑)。解釋一下:向上面的例子一樣,(a,2)(2,b),是即從a點經過2點到b點的距離,因為x矩陣和y矩陣都是走k條邊後的最短路徑,那麽x矩陣中的(a,2)是走k步後的最短路徑,(2,b)也是,那麽他們相加不就是走k+k條邊後的最短路徑嗎?其他的矩陣一樣。
然後,就可以套用快速冪的模板了,只不過將以前的乘改成加了,也就是倍增的思想的,比如對於走10條邊,它的二進制是1010,那麽我們就讓在走2(10)邊時的矩陣 乘以 8(1000)邊的矩陣,得到走10條邊的矩陣即開始時由1->2->4->8->16……即倍增中的2次冪。
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<map> 4 #include<cstring> 5 6 using namespace std; 7 const int MAXN = 210; 8 9 int Hash[1010]; 10 int n,k,q,z,tn; 11 12 int read() 13 { 14 int x = 0,f = 1;char ch = getchar(); 15 while (ch<‘0‘||ch>‘9‘) {if (ch=‘-‘) f=-1;ch = getchar(); } 16 while (ch>=‘0‘&&ch<=‘9‘){x = x*10+ch-‘0‘;ch = getchar(); } 17 return x*f; 18 } 19 20 struct Matrix{ 21 int a[MAXN][MAXN]; 22 Matrix operator * (const Matrix &x) const 23 { 24 Matrix c; 25 memset(c.a,0x3f,sizeof(c.a)); 26 for (int k=1; k<=tn; k++) 27 for (int i=1; i<=tn; ++i) 28 for (int j=1; j<=tn; ++j) 29 c.a[i][j] = min(c.a[i][j],a[i][k]+x.a[k][j]); 30 return c; 31 } 32 }s,ans; 33 void ksm() 34 { 35 ans = s; 36 k--; 37 for (; k; k>>=1) 38 { 39 if (k&1) ans = ans*s; 40 s = s*s; 41 } 42 } 43 int main() 44 { 45 k = read();n = read();q = read();z = read(); 46 memset(s.a,0x3f,sizeof(s.a)); 47 for (int x,y,w,i=1; i<=n; ++i) 48 { 49 w = read();x = read();y = read(); 50 if (!Hash[x]) Hash[x] = ++tn; 51 if (!Hash[y]) Hash[y] = ++tn; 52 s.a[Hash[x]][Hash[y]] = s.a[Hash[y]][Hash[x]] = w; 53 } 54 ksm(); 55 printf("%d",ans.a[Hash[q]][Hash[z]]); 56 return 0; 57 }
poj3613:Cow Relays(倍增優化+矩陣乘法floyd+快速冪)