zoukankan      html  css  js  c++  java
  • [CF1483D] Useful Edges

    前言

    如果你毫无思路,考虑暴力!然后优化它!

    题目

    CF

    洛谷

    讲解

    如果你想容斥,那么你已经没救了。

    ( t Floyd) 应该不用讲吧。

    我们先想暴力,枚举一条边,然后在三元组里面检验,时间复杂度是 (O(mq)=O(n^4))

    我们发现枚举边似乎不是很能优化,于是我们考虑是否能够不枚举三元组。

    我们把一条边是好边的条件写下来:存在一个三元组 (l_{i,j}ge dis_{i,u}+w_{u,v}+dis_{v,j})

    移项: (l_{i,j}-dis_{i,u}ge w_{u,v}+dis_{v,j})

    我们发现 (RHS) 已经和 (i) 无关,可以 (O(nm)) 做,这时我们只需要知道 (LHS) 即可。

    (LHS) 最大值为 (MAX_{j,u}),显然可以用 (O(qn)) 的时间复杂度预处理,注意一个三元组中的 (l) 既可以代表 (l_{i,j}) 也可以代表 (l_{j,i})

    此时时间复杂度已经降为了 (O(n^3)) 级别。

    代码

    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read(); m = Read();
    	for(int i = 1;i <= n;++ i) 
    		for(int j = 1;j <= n;++ j)
    			if(i ^ j) dis[i][j] = INF;
    	for(int i = 1;i <= m;++ i)
    	{
    		u[i] = Read(),v[i] = Read(),w[i] = Read();
    		dis[u[i]][v[i]] = dis[v[i]][u[i]] = w[i];
    	}
    	for(int k = 1;k <= n;++ k)
    		for(int i = 1;i <= n;++ i)
    			for(int j = 1;j <= n;++ j)
    				dis[i][j] = Min(dis[i][j],dis[i][k]+dis[k][j]);
    	for(int Q = Read(); Q ;-- Q)
    	{
    		int i = Read(),j = Read(),l = Read();
    		for(int u = 1;u <= n;++ u) MAX[j][u] = Max(MAX[j][u],l-dis[i][u]),MAX[i][u] = Max(MAX[i][u],l-dis[j][u]);
    	}
    	for(int i = 1;i <= m;++ i)
    		for(int j = 1;j <= n;++ j)
    			if(MAX[j][u[i]] >= w[i]+dis[v[i]][j])
    			{
    				ans++;
    				break;
    			}
    	Put(ans);
    	return 0;
    }
    
  • 相关阅读:
    UVA 11997 K个最小和
    UVALive 3135阿格斯
    UVA 10635 王子和公主
    UVA11991线性查询
    UVA1339仿射和换位密码
    UVA 10382喷水设施
    LA2965字符串合并
    FatMouse's Speed--hdu1160(dp+输出路径)
    Dividing--hdu1059(动态规划)
    Piggy-Bank--hdu1114(完全背包)
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/14791932.html
Copyright © 2011-2022 走看看