zoukankan      html  css  js  c++  java
  • 洛谷 P2966 [USACO09DEC]牛收费路径Cow Toll Paths 题解

    一、题目:

    洛谷原题

    二、思路:

    此题可加深对Floyd的理解。

    首先我们应该知道,Floyd中G[i][j]实际上是一个滚动数组,真正的DP数组是G[k][i][j],其中k是阶段.G[k][i][j]表示只经过(1 sim k)这些节点,i到j的最短距离。

    那么如果我们还原这种DP状态,按照k的点权从小到大的顺序转移,那么我们询问的时候就只需要从1到n枚举最大点,用该点的点权加上i到j的最短路更新答案即可。

    还有一个细节,注意到G[i][j]保存的最短路不经过i和j本身,所以更新答案时注意用i的点权、j的点权与枚举的最大点的点权取max再加上最短路。

    算法博大精深,切不可一知半解,如果不知道Floyd的本质,那这个题也就做不出来了。(这句话是留给我的。)

    三、代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    #define LL long long
    #define FILEIN(s) freopen(s".in","r",stdin)
    #define FILEOUT(s) freopen(s".out","w",stdout)
    #define mem(s,v) memset(s,v,sizeof(s))
    
    using namespace std;
    inline LL read(void){
    	LL x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    	return f*x;
    }
    
    const int maxn=255;
    
    int n,m,q;
    int G[maxn][maxn][maxn];
    int ref[maxn];
    
    struct Weight{
        int id,w;
        inline friend bool operator <(Weight x,Weight y){
            return x.w<y.w;
        }
    }a[maxn];
    
    int main(){
        mem(G,0x3f);
        n=read();m=read();q=read();
        for(register int i=1;i<=n;++i){
            a[i].id=i;
            a[i].w=read();
            G[i][i][0]=0;
        }
        sort(a+1,a+n+1);
        for(register int i=1;i<=n;++i){
            ref[a[i].id]=i;
        }
        for(register int i=1;i<=m;++i){
            int s=ref[read()],t=ref[read()],l=read();
            G[t][s][0]=G[s][t][0]=min(G[s][t][0],l);
        }
        for(register int k=1;k<=n;++k){
            for(register int i=1;i<=n;++i){
                for(register int j=1;j<=n;++j){
                    G[i][j][k]=min(G[i][j][k],G[i][k][k-1]+G[k][j][k-1]);
                    G[i][j][k]=min(G[i][j][k],G[i][j][k-1]);
                }
            }
        }
        for(register int step=1;step<=q;++step){
            int s=ref[read()],t=ref[read()];
            int minn=0x3f3f3f3f;
            for(register int i=1;i<=n;++i){
                minn=min(minn,G[s][t][i]+max(max(a[s].w,a[t].w),a[i].w));
            }
            printf("%d
    ",minn);
        }
    	return 0;
    }
    
    
  • 相关阅读:
    [Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F
    [Codeforces Round #611 (Div. 3)] C. Friends and Gifts (随机大法好)
    [Hello 2020] D. New Year and Conference (ST表,排序)
    [Hello 2020] C. New Year and Permutation (组合数学)
    Codeforces Beta Round #7 C. Line (扩展欧几里德)
    扩展欧几里德
    Codeforces Round #349 (Div. 2) D. World Tour (最短路)
    HDU 4052 Adding New Machine (线段树+离散化)
    HDU 3265 Posters (线段树+扫描线)(面积并)
    HDU 1828 Picture (线段树+扫描线)(周长并)
  • 原文地址:https://www.cnblogs.com/little-aztl/p/11197475.html
Copyright © 2011-2022 走看看