题目链接:https://ac.nowcoder.com/acm/contest/6234/H
题目大意:你可以按题目规则规则一个矩阵
图片说明
然后问你从(Sr, Sc)到(Tr, Tc)的最大分数,如果(x, y)没有访问过,那么你从(i, j)访问到(x, y)得到发分数为V(i, j)*V(x, y)。

思路:因为vij>0那么我们一定是把所有的点访问完的代价最大。然后每个点向周围四个方向连边就是求一个最大生成树。
优化:我们从题目可以知道边权<10000,边可以桶排。得到n-1条边就break。

#include<bits/stdc++.h>
#define LL long long
using namespace std;

LL x[1000*1005];
struct node{
    LL u, v, w;
};
int f[1000*1005*2];
int fd(int x){
    if(f[x]==-1) return x;
    return f[x]=fd(f[x]);
}
vector<node> v[10005];
inline int read(){
    int 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<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

int main(){

    int T, cas=1; scanf("%d", &T);
    while(T--){
        for(int i=0; i<=10000; i++) {
            v[i].clear();//必须先加这一句,否则直接用v.shrink_to_fit(),无法释放内存
            v[i].shrink_to_fit();
        }
        LL N, M, Sr, Sc, Tr, Tc;
        N=read(), M=read(), Sr=read(), Sc=read(), Tr=read(), Tc=read();
        LL x1, x2, A, B, C, P;
        x[1]=read(), x[2]=read(), A=read(), B=read(), C=read(), P=read();
        f[1]=f[2]=-1;
        for(int i=3; i<=N*M; ++i){
            x[i]=(A*x[i-1]+B*x[i-2]+C)%P;
            f[i]=-1;
        }
        for(int i=1; i<=N; ++i){
            for(int j=1; j<=M; ++j){
                if(i+1<=N){
                    int s = (i-1)*M + j;
                    int t = i*M + j;
                    v[x[s]*x[t]].push_back({s, t});
                }
                if(j+1<=M){
                    int s = (i-1)*M + j;
                    int t = (i-1)*M+j+1;
                    v[x[s]*x[t]].push_back({s, t});
                }
            }
        }
        LL ans=0, now=N*M-1;
        for(int i=10000; i>=0&&now>0; i--){
            for(auto To: v[i]){
                int x=fd(To.u), y=fd(To.v);
                if(x!=y){
                    ans+=i;
                    f[x]=y;
                    --now;
                }
            }
        }
        printf("Case #%d: %lld\n", cas++, ans);
    }

    return 0;
}