|
Posted on 2011-05-02 17:39 Uriel 阅读(764) 评论(0) 编辑 收藏 引用 所属分类: POJ 、 图论
这是在DY大牛第六期专题里列出的题目之一.
话说搞ACM也2年多了, 竟然用矩阵乘法+Floyd的题目都还没有做过... 上周的组队赛遇到一道题才听说... (没有拜读matrix67的神文... 检讨下... )
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) /**//*
POJ 3613 Cow Relays
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
-------Classify: Floyd+矩阵乘法
----Description: 求从S到T恰好经过K条边(可重复走)的最短路
-----------------K<=1e6, m<100(边数)
---Sample Input:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
2 6 6 4----------//K m s t
11 4 6-----------//length x<->y
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
--Sample Output:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
10
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
-----Time Limit: 1000Ms
---------Source: USACO 2007 November Gold
-------Solution:
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
By Solution Report
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
01邻接矩阵A的K次方C=A^K,C[i][j]表示i点到j点正好经过K条边的路径数
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
对应于这道题,对邻接图进行K次floyd之后,C[i][j]就是点i到j正好经过K条边的最短路
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif)
---------Status: AC C++ 532Ms
-----------Date: 2011.05.02
------Reference: http://hi.baidu.com/aconly/blog/item/23fb73acc1d874004b36d634.html
-----------Code:
*/
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 1010
#define INF 0x3f3f3f3f
typedef int M[N][N];
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
int k, m, s, t, v;
int ans[N][N], adj[N][N], vis[N], vtx[N], dis[N][N], tp[N][N];
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) void floyd(M c, M a, M b) {
int i, j, k;
for (k = 0; k < v; ++k)
for (i = 0; i < v; ++i)
for (j = 0; j < v; ++j)
if (c[vtx[i]][vtx[j]] > a[vtx[i]][vtx[k]] + b[vtx[k]][vtx[j]])
c[vtx[i]][vtx[j]] = a[vtx[i]][vtx[k]] + b[vtx[k]][vtx[j]];
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) void copy(M a, M b) {
int i, j;
for (i = 0; i < v; ++i)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for (j = 0; j < v; ++j) {
a[vtx[i]][vtx[j]] = b[vtx[i]][vtx[j]];
b[vtx[i]][vtx[j]] = INF;
}
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) void BS(int k) {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) while (k) {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if (k & 1) {
floyd(dis, ans, adj);
copy(ans, dis);
}
floyd(tp, adj, adj);
copy(adj, tp);
k >>= 1;
}
}
![](http://www.cppblog.com/Images/OutliningIndicators/None.gif)
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif) int main() {
int i, j, x, y, w;
scanf("%d %d %d %d", &k, &m, &s, &t);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for (i = 0; i <= 1001; ++i) {
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for (j = 0; j <= 1001; ++j) {
adj[i][j] = INF;
tp[i][j] = INF;
dis[i][j] = INF;
ans[i][j] = INF;
}
ans[i][i] = 0;
}
v = 0;
memset(vis, 0, sizeof(vis));
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) for (i = 0; i < m; ++i) {
scanf("%d %d %d", &w, &x, &y);
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if (!vis[x]) {
vis[x] = 1;
vtx[v++] = x;
}
![](http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif) if (!vis[y]) {
vis[y] = 1;
vtx[v++] = y;
}
if (adj[x][y] > w)
adj[x][y] = adj[y][x] = w;
}
BS(k);
printf("%d\n", ans[s][t]);
return 0;
}
|