zoukankan      html  css  js  c++  java
  • P6190 [NOI Online 入门组]魔法

    P6190 [NOI Online 入门组]魔法

    题目描述
    分析

    这道题要求的是从1到(n)的最短路,其中有(k)次机会可以将一条边暂时的变为相反数,一条边可以走无数次

    注意到无数次这个比较奇怪的要求,也就是说可以不考虑重复,那么设(a_{k,i,j})表示从(i)(j)(k)次魔法的最小值,那么显然(a_{k,i,j}=min(a_{u,i,v}+a_{k-u,v,j})),即把(i)(j)分为两段,那么首先对于(k=0)的情况,可以直接Floyd解决,对于(k=1)可以枚举所有的边解决,然后我们就得到了一个矩阵M,我们显然可以定义一种矩阵乘法(a*b=min(a_{i,u}+b_{u,j}))符合我们上面推出来的转移方程

    那么对于(k)的情况,即用矩阵快速幂求出(M^k)即可

    代码
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=105;
    struct Node
    {
    	long long matrix[N][N];
    }a,b;
    int n,m,k,edge[2505][3];
    
    void Input()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	memset(a.matrix,63,sizeof(a.matrix));
    	memset(b.matrix,63,sizeof(b.matrix));
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		a.matrix[x][y]=z;
    		edge[i][0]=x; edge[i][1]=y; edge[i][2]=z;
    	}
    	return;
    }
    
    void Prepare()
    {
    	for(int i=1;i<=n;i++) a.matrix[i][i]=0;
    	for(int kk=1;kk<=n;kk++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    //				if( i!=j && i!=kk && j!=kk )
    					a.matrix[i][j]=min(a.matrix[i][j],a.matrix[i][kk]+a.matrix[kk][j]);
    //	for(int i=1;i<=n;i++)
    //	{
    //		for(int j=1;j<=n;j++) cout<<a.matrix[i][j]<<" ";
    //		cout<<endl;
    //	}
    	for(int i=1;i<=n;i++) b.matrix[i][i]=0;
    	for(int kk=1;kk<=m;kk++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				b.matrix[i][j]=min(b.matrix[i][j],min(a.matrix[i][j],a.matrix[i][edge[kk][0]]+a.matrix[edge[kk][1]][j]-edge[kk][2]));
    //	for(int i=1;i<=n;i++)
    //	{
    //		for(int j=1;j<=n;j++) cout<<b.matrix[i][j]<<" ";
    //		cout<<endl;
    //	}
    	return;
    }
    
    Node matrix_mul(Node A,Node B)
    {
    	Node tem;
    	memset(tem.matrix,63,sizeof(tem.matrix));
    	for(int kk=1;kk<=n;kk++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				tem.matrix[i][j]=min(tem.matrix[i][j],A.matrix[i][kk]+B.matrix[kk][j]);
    	return tem;
    }
    
    long long matrix_pow(Node x,int y)
    {
    	Node tem=a;
    	while( y )
    	{
    		if( y%2 ) tem=matrix_mul(x,tem);
    		x=matrix_mul(x,x);
    		y/=2;
    	}
    	return tem.matrix[1][n];
    }
    
    void work()
    {
    	if( k==0 ) printf("%lld",a.matrix[1][n]);
    	else printf("%lld",matrix_pow(b,k));
    	return;
    }
    
    int main()
    {
    	Input();
    	Prepare();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    ubuntu的apt
    sudo命令
    MySQL导出数据到csv文件
    MySQL导出数据到文件报错
    git_backup.py gitlab项目备份
    java中图像与数组转换
    mongodb转elasticsearch
    impyla-0.14.2.2安装注意事项
    python3.7.3升级 with-openssl openssl-1.0.2a
    hadoop自带性能测试
  • 原文地址:https://www.cnblogs.com/BZDYL/p/12507266.html
Copyright © 2011-2022 走看看