奶牛接力【洛谷P2886 [USACO07NOV]牛继电器Cow Relays】图的矩阵乘法

图的矩阵乘法

给定一个N个节点的无向图(可以证明有向图也满足要求)

设G[u][v]=G[v][u]=1表示u,v有一条路径

我们模拟矩阵自乘G2[u][v]= ∑ ( i = 1 , n ) G [ u ] [ i ] ∗ G [ i ] [ v ] \sum(i=1,n)G[u][i]*G[i][v] (i=1,n)G[u][i]G[i][v]
这表示u到v的路径上只经过中间点i的路径条数
即u到v的路径上经过两条边的路径条数
以此类推,Gk[u][v]表示在u到v的路径上经过k条边的路径条数
p.s.当路径上有重边时,G[u][v]表示u到v的路径条数

接下来,我们讨论求u到v经过k条边的最短路

设G[u][v]表示u到v仅经过一条边的最短路
G2[u][v]=Mini=1,n(G[u][i]+G[i][v]);
这个。。。很显然吧
他同样满足矩阵乘法的性质
所以可以愉快的快速幂了,只是把矩阵A[i][k]*B[k][j]定义为min{a[i][k]+b[k][j]}
例题:Cow Relays
P2886 [USACO07NOV]牛继电器Cow Relays

题目描述
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.

给出一张无向连通图,求S到E经过k条边的最短路。

输入格式

  • 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

输出格式

  • Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.

输入输出样例
输入 #1 复制
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
输出 #1 复制
10
对于这道题目的翻译,我已无力吐槽,差点没有双倍经验
直接上代码了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
struct Matrix
{
    long long v[210][210];
};
Matrix G,ans;
int K,T,S,E;
long long n;
long long p[2010];
inline long long min(long long x,long long y)
{
	return x<y?x:y;
}
Matrix mul(Matrix a,Matrix b)
{
    Matrix c;
    memset(c.v,0x3f,sizeof(c.v));
    int i,j,k;
    for(k=1;k<=n;k++)
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				c.v[i][j]=min(c.v[i][j],a.v[i][k]+b.v[k][j]);
    return c;
}
void ksm(int x)
{
    while(x)
    {
        if(x&1) 
			ans=mul(ans,G);
        G=mul(G,G);
        x>>=1;
    }
}
int main()
{
	freopen("relay.in","r",stdin);
	freopen("relay.out","w",stdout);
    int i;
	scanf("%d%d%d%d",&K,&T,&S,&E);
    memset(G.v,0x3f,sizeof(G.v));
    memset(ans.v,0x3f,sizeof(ans.v));
    for(i=1;i<=T;i++)
	{
        int w,x,y;
        scanf("%d%d%d",&w,&x,&y);
        if(!p[x]) p[x]=++n;
		if(!p[y]) p[y]=++n;
        G.v[p[x]][p[y]]=G.v[p[y]][p[x]]=min(w,G.v[p[y]][p[x]]);
    }
    for(i=1;i<=n;i++) 
		ans.v[i][i]=0;
    ksm(K);
    printf("%lld\n",ans.v[p[S]][p[E]]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值