zoukankan      html  css  js  c++  java
  • 洛谷P1613 跑路

    题目

    倍增

    直接用图论算法必然解决不了这个问题,所以可以使用倍增算法优化。

    我们遇到这个题该怎么想,首先,题目要求的值是1到n的最小代价。代价是路径的二进制中1的个数。

    我们先预处理出每两点之间是否有边权和为(1 << k)的路径。这样的话,代价预处理就可以只需考虑1的情况,因为每个数都可以由(1<<k1)+(1<<k2)所累加而来,所以像2,3这种数都可以用1凑出来。

    处理之后,一开始连接的边代价都为1,然后可以找到许多可以横跨许多点的代价为1的路径,这样的话, 就用floyd转移代价即可。

    #include <bits/stdc++.h>
    #define N 1000111		
    #define int long long	
    using namespace std;	
    int n, m, mp[101][101];
    int cek[101][101][100]; //cek[i][j][k]表示是否i到j之间有边权和为(1 << k)的路径
    signed main()			
    {
     	scanf("%lld%lld", &n, &m);
     	memset(mp, 10, sizeof(mp));
     	for (int i = 1; i <= m; i++)
     	{
    		int a, b;
    		scanf("%lld%lld", &a, &b);
    		cek[a][b][0] = 1;
    		mp[a][b] = 1;
     	}	
     	for (int t = 1; t <= 64; t++)
     	{ 
     		for (int k = 1; k <= n; k++)
    			for (int i = 1; i <= n; i++)
    				for (int j = 1; j <= n; j++)
    					if (cek[i][k][t - 1] && cek[k][j][t - 1])
    					{
    						cek[i][j][t] = 1;
    						mp[i][j] = 1;
    	         		}
    	} 
    	for (int k = 1; k <= n; k++)	
    		for (int i = 1; i <= n; i++)
    			for (int j = 1; j <= n; j++)
    				mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
     	printf("%lld", mp[1][n]);
     	return 0;
    }
    /*
    7 8
    1 6
    5 1
    6 4
    4 5
    5 2
    3 7
    7 5
    2 3
    rignt ans: 2
    */
    
  • 相关阅读:
    position之属性
    Grid网格布局
    position 属性指定了元素的定位类型
    注册表单
    简单页面
    自我介绍
    正则表达式
    Dom和Bom
    颜色和单位
    伪类和伪元素的区别
  • 原文地址:https://www.cnblogs.com/liuwenyao/p/11542005.html
Copyright © 2011-2022 走看看