zoukankan      html  css  js  c++  java
  • Codeforces Round #582 (Div. 3) G. Path Queries

    Codeforces Round #582 (Div. 3) G. Path Queries

    题目描述

    个人感觉这道题目的思路比较像最小瓶颈生成树,首先我们要理解什么是最小瓶颈生成树,最小瓶颈生成树是在一张图上生成一棵树要求最大的边最小,可以感性理解一下,最小生成树一定是最小瓶颈生成树,但最小瓶颈生成树不一定是最小生成树,所以我们可以用最小生成树来做这道题目。

    回忆(kruskal)最小生成树的过程,当前加进去的边一定是使这些联通块中的点两两联通的最大边的最小值。如果只有一个联通块就直接输出(n*(n-1)/2)就可以了,(其中(n)是当前联通的点的个数),如果有多个联通块每个把它们相加就可以了。但是如果这次操作联通的是两个联通块,这样就会重算,需要判断一下。为了方便我们直接计算每次连上这条边对点对数量的贡献就是(size[a]*size[b])(由乘法原理易得)。所以我们只需要在原来的点对数上加上就可以了。

    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<cstdio>
    #define ll long long
    using namespace std;
    const int N=2e5+100;
    struct edge{
    	int s,e,v;
    };
    vector<edge>ed;
    int n,m,maxq;
    int f[N],size[N],q[N];
    ll ans[N];
    inline bool cmp(edge a,edge b) {return a.v<b.v;}
    inline int getf(int x) {return f[x]==x ? x:f[x]=getf(f[x]);}
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n-1;i++)
    	{
    		int s,e,v;
    		scanf("%d%d%d",&s,&e,&v);
    		ed.push_back((edge){s,e,v});
    	}
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d",q+i);
    		maxq=max(maxq,q[i]);
    	}
    	for (int i=1;i<=n;i++)
    	{
    		size[i]=1;
    		f[i]=i;
    	}
    	sort(ed.begin(),ed.end(),cmp);
    	int be=0,nv=0;
    	for (int i=0;i<(int)ed.size();i++)
    	{
    		int a=getf(ed[i].s),b=getf(ed[i].e);
    		nv=ed[i].v;
    		ll now=0;
    		if (a!=b)
    		{
    			now=(ll)size[a]*size[b];
    			size[b]+=size[a];
    			size[a]=0;
    			f[a]=b;
    		}
    		ans[nv]+=now;
    	}
    	for (int i=1;i<=maxq;i++)
    	ans[i]+=ans[i-1];
    	for (int i=1;i<=m;i++)
    	cout<<ans[q[i]]<<" ";
    	return 0;
    }
    
  • 相关阅读:
    c++ 内存管理方式
    4.2学习总结
    PTA面向对象程序设计6-3 面积计算器(函数重载)
    3.26学习总结
    PTA——c++面向对象基础
    3.17学习总结.listview用法总结
    3.16学习总结
    3.15学习总结(Python爬取网站数据并存入数据库)
    android开发使用jxl创建Excel
    第一次结对作业
  • 原文地址:https://www.cnblogs.com/last-diary/p/11446375.html
Copyright © 2011-2022 走看看