【题&结论】【图(Floyd)&矩阵】NKOJ 1895 奶牛接力赛

40 篇文章 0 订阅
14 篇文章 0 订阅

NKOJ 1895 奶牛接力赛
时间限制 : 10000 MS 空间限制 : 65536 KB

问题描述
为了锻炼身体,N(2 ≤ N ≤ 1,000,000)只奶牛决定用牧场里的T (2 ≤ T ≤ 100)条小路进行一场跑步接力赛。
每条小路连接两个不同的交点(1 ≤ I1i ≤ 1,000; 1 ≤ I2i ≤ 1,000),每个交点至少连接两条小路。奶牛们知道每条小路的长度(1<=长度<=1,000),两个交点间最多只有一条小路直接相连。
为了完成接力赛,赛前这N头奶牛可以把自己安置在任意交点上(每个交点上可以安排多只奶牛)。但是奶牛们必须把自己安置在恰当的位置上,这样才能一个接一个地把接力棒传到指定的终点。
请写一个程序帮助奶牛们找到合适的位置。请找出从起点(S)到终点(E)的恰好经过了N头奶牛的最短路径。

输入格式
第一行,4个空格间隔的整数N,T,S,E
接下来T行,每行3个空格间隔的整数,z,x,y表示交点x和y之间有条长度为z的小路直接相连。

输出格式
一个整数,表示从起点S到终点E的恰好经过了N头奶牛的最短路的长度。

样例输入
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9

样例输出
10

来源 USACO

思路:
1、考虑Floyd思想将矩阵乘法替换为Floyd,用以求最短路径
2、多次Floyd仍用蒙哥马利优化。
3、其他:
因为路的数量不超过100所以点的数量不会超过100,而题目所给点编号范围为1000,所以需要压缩。并能减少Floyd时间复杂度。
ans数组初值中点到自己距离为0,到其他点距离为inf。可理解为ans&a后a不变
c数组初值全为inf。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int inf=1e9;
const int need=103;
typedef int int_[need][need];

int_ ans,a,c; 
int n,t,x,y,m=0,belong[1000];

void floyd(int_ a,int_ b)
{
    for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) c[i][j]=inf;
    for(int k=1;k<=m;k++)
     for(int i=1;i<=m;i++)
      for(int j=1;j<=m;j++)
       c[i][j]=min(c[i][j],a[i][k]+b[k][j]);
    for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) a[i][j]=c[i][j];
}

void solve(int b)
{
    for(int i=1;i<=m;i++) ans[i][i]=0;
    while(b)
    {
        if(b&1) floyd(ans,a);
        b>>=1;
        floyd(a,a);
    }
}

int main()
{
    scanf("%d%d%d%d",&n,&t,&x,&y);
    for(int i=1,p,q,z;i<=t;i++)
    {
        scanf("%d%d%d",&z,&p,&q);
        if(belong[p]==0) belong[p]=++m;
        if(belong[q]==0) belong[q]=++m;
        a[belong[p]][belong[q]]=a[belong[q]][belong[p]]=z;
    }
    for(int i=1;i<=m;i++)
     for(int j=1;j<=m;j++) 
     {
        if(a[i][j]==0) a[i][j]=inf;
        ans[i][j]=inf;
     }
    solve(n);
    printf("%d",ans[belong[x]][belong[y]]);
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值