POJ - 3613 Cow Relays【矩阵DP】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/niiick/article/details/82805835

Time limit1000 ms
Memory limit65536 kB

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.

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.


题目分析

图的邻接矩阵有一个性质
G [ u ] [ v ] G[u][v] 表示 u u v v 恰好经过一条边的路径的条数
那么 G k [ u ] [ v ] G^k[u][v] 则表示恰好经过 K K 条边的
可以用矩阵快速幂计算

这题我们对矩阵乘法的定义稍加修改
我们把原先矩乘的乘法改成加法求和改成求最小值
G 2 [ u ] [ v ] = M i n i = 1 n ( G [ u ] [ i ] + G [ i ] [ v ] ) G^2[u][v]=Min_{i=1}^n(G[u][i]+G[i][v])
G [ u ] [ v ] G[u][v] 表示 u u v v 恰好经过一条边的路径的最短路
那么 G k [ u ] [ v ] G^k[u][v] 则表示恰好经过 K K 条边的

重新定义计算后依然满足结合律,可以使用矩阵快速幂计算

上述在这篇博客中都有具体解释

矩阵乘法 x 图的邻接矩阵

注意此题需要将节点编号离散化


#include<iostream>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;

int read()
{
    int f=1,x=0;
    char ss=getchar();
    while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
    while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
    return f*x;
}

const int maxn=500;
int n,m,s,t,tot;
int hh[1000010];
struct node{int a[maxn][maxn];}rem;

node mul(node x,node y)
{
    node ans;
    memset(ans.a,63,sizeof(ans.a));
    for(int k=1;k<=tot;++k)
    for(int i=1;i<=tot;++i)
    for(int j=1;j<=tot;++j)
    ans.a[i][j]=min(ans.a[i][j],x.a[i][k]+y.a[k][j]);
    return ans;
}

node qpow(node a,int k)
{
    node ans=a; k--;
    while(k>0){
        if(k&1) ans=mul(ans,a);
        a=mul(a,a);
        k>>=1;
    }
    return ans;
}

int main()
{
    n=read();m=read();s=read();t=read();
    memset(rem.a,63,sizeof(rem.a));
    for(int i=1;i<=m;++i)
    {
    	int dis=read(),u=read(),v=read();
    	if(!hh[u]) hh[u]=++tot;
    	if(!hh[v]) hh[v]=++tot;
    	if(rem.a[hh[u]][hh[v]]>dis)
    	rem.a[hh[u]][hh[v]]=rem.a[hh[v]][hh[u]]=dis;
    }
    node tt=qpow(rem,n);
    printf("%d",tt.a[hh[s]][hh[t]]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/niiick/article/details/82805835