[洛谷P2886] 牛继电器Cow Relays

旧时模样 提交于 2019-12-03 07:00:15

问题描述

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.

输入格式

* 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.

样例输入

2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9

样例输出

10

题目大意

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

解析

倍增Floyd模版题。利用矩阵快速幂的形式可以在\(log\)的时间内处理经过k条路径的最短路。

虽然一共有1000000个点,但是因为只有100条边,可以直接用100条边的端点建图,离散化编号即可。

代码

#include <iostream>
#include <cstdio>
#define int long long
#define N 1000002
using namespace std;
const int inf=1<<30;
struct Matrix{
    int a[500][500];
}S;
int n,m,s,t,i,j,id[N],cnt;
int read()
{
    char c=getchar();
    int w=0;
    while(c<'0'||c>'9') c=getchar();
    while(c<='9'&&c>='0'){
        w=w*10+c-'0';
        c=getchar();
    }
    return w;
}
Matrix mult(Matrix a,Matrix b)
{
    Matrix c;
    for(int i=1;i<=cnt;i++){
        for(int j=1;j<=cnt;j++) c.a[i][j]=inf;
    }
    for(int k=1;k<=cnt;k++){
        for(int i=1;i<=cnt;i++){
            for(int j=1;j<=cnt;j++) c.a[i][j]=min(c.a[i][j],a.a[i][k]+b.a[k][j]);
        }
    }
    return c;
}
Matrix poww(Matrix a,int b)
{
    b--;
    Matrix ans=a,base=a;
    while(b){
        if(b&1) ans=mult(ans,base);
        base=mult(base,base);
        b>>=1;
    }
    return ans;
}
signed main()
{
    n=read();m=read();s=read();t=read();
    for(i=1;i<=2*m;i++){
        for(j=1;j<=2*m;j++) S.a[i][j]=inf;
    }
    for(i=1;i<=m;i++){
        int w=read(),u=read(),v=read();
        if(!id[u]) id[u]=++cnt;
        if(!id[v]) id[v]=++cnt;
        S.a[id[u]][id[v]]=S.a[id[v]][id[u]]=w;
    }
    Matrix ans=poww(S,n);
    cout<<ans.a[id[s]][id[t]]<<endl;
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!