• [CF576D]Flights for Regular Customers


    题目大意:有一张$n$个点$m$条边的有向图,第$i$条边有个权值$d_i$表示至少要走$d_i$条边才可以经过这条边(可重复),问从点$1$到点$n$最少经过几条边(重复算多次),无解输出$-1$。$n,mleqslant150,d_ileqslant 10^9$

    题解:按$d_i$排序,一条条加入转移矩阵,可以用邻接矩阵算出走恰好$k$次可以到达的位置。可以发现,在一个行的转移矩阵下,若点$1$可以走到点$n$,最多走$n-1$步。于是可以先暴力走$n-1$次,若还不能到达$n$,就用矩阵快速幂计算。复杂度$O(n^4m(log_2 d+n))$。可以令一个向量表示点$1$可以到达的点,就变成向量乘矩阵,复杂度少一个$n$,已经可以通过了。也可以用$mathrm{bitset}$优化乘法,复杂度$O(dfrac{n^3m(log_2d+n)}{omega})$

    卡点:

    C++ Code:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <bitset>
    const int maxn = 160;
    typedef std::bitset<maxn> B8;
    
    int n, m;
    struct Matrix {
    	B8 s[maxn];
    	Matrix() { for (int i = 0; i < n; ++i) s[i].reset(); }
    	Matrix operator * (const Matrix &rhs) {
    		Matrix res;
    		for (int i = 0; i < n; ++i)
    			for (int j = 0; j < n; ++j)
    				if (s[i][j]) res.s[i] |= rhs.s[j];
    		return res;
    	}
    } base;
    B8 operator * (const B8 &lhs, const Matrix &rhs) {
    	B8 res; res.reset();
    	for (int i = 0; i < n; ++i)
    		if (lhs[i]) res |= rhs.s[i];
    	return res;
    }
    B8 R;
    
    struct Edge {
    	int a, b, d;
    	inline bool operator < (const Edge &rhs) const { return d < rhs.d; }
    } e[maxn];
    
    int check(int N) {
    	for (int i = 1; i <= N; ++i) {
    		R = R * base;
    		if (R[n - 1]) return i;
    	}
    	return N + 1;
    }
    void pw(int p) {
    	Matrix b = base;
    	for (; p; p >>= 1, b = b * b) if (p & 1) R = R * b;
    }
    int solve() {
    	int p = 1, res = 0;
    	for (; p <= m && e[p].d == 0; ++p) base.s[e[p].a - 1].set(e[p].b - 1);
    	if (p == 1) return 0;
    	R.set(0);
    	for (int t, o; p <= m; ++p) {
    		t = e[p].d - e[p - 1].d;
    		if (t <= n) {
    			o = check(t);
    			if (o > t) res += t;
    			else return res + o;
    		} else {
    			o = check(n);
    			if (o > n) pw(t - n), res += t;
    			else return res + o;
    		}
    		base.s[e[p].a - 1].set(e[p].b - 1);
    	}
    	int o = check(n);
    	if (o > n) return 0;
    	return res + o;
    }
    
    int main() {
    	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
    	std::cin >> n >> m;
    	for (int i = 1; i <= m; ++i)
    		std::cin >> e[i].a >> e[i].b >> e[i].d;
    	std::sort(e + 1, e + m + 1);
    	int ans = solve();
    	if (!ans) std::cout << "Impossible
    ";
    	else std::cout << ans << '
    ';
    	return 0;
    }
    

      

  • 相关阅读:
    浅谈Vue基础知识(二)
    浅谈Vue基础知识(一)
    ES 6
    网易DBA私享会分享会笔记2
    网易DBA私享会分享会笔记1
    centos6.5适用的国内yum源:网易、搜狐
    如何去除 ckeditor 上传图片后在原码中留下的 style="width: 100%;height:100px"之类的代码呢?
    关于json.ajax ,php的那点事
    去掉所有的html标签
    [CentOS 0010] CentOS 配置mysql允许远程登录
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/11788401.html
Copyright © 2020-2023  润新知