• 【旅游】题解


    题目

    题目描述

    这里写图片描述

    输入

    这里写图片描述

    输出

    这里写图片描述

    样例输入

    1
    5 5 3
    2 3 6334
    1 5 15724
    3 5 5705
    4 3 12382
    1 3 21726
    6000
    10000
    13000
    

    样例输出

    2
    6
    12
    

    数据制约

    这里写图片描述

    分析

    先把路径和询问也按权值排序,依次按权值把边加入图中,则增加的边数就是边的两头所在的连通块的节点数的积再乘2(如果在同一个连通块就不用),再用并查集维护就可以了。

    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    int n,m,tot,q,test;
    using namespace std;
    int a[110000][4],bcj[21000],ans[6000],bl[21000],qu[6000][3];
    //bl数组是以x为祖宗的连通块的节点数,bcj即并查集
    void q1(int l,int r)
    {
    	int i=l,j=r,mid=a[(l+r)/2][3],e;
    	while(i<j)
    	{
    		while(a[i][3]<mid) i++;
    		while(a[j][3]>mid) j--;
    		if(i<=j)
    		{
    			e=a[i][2];
    			a[i][2]=a[j][2];
    			a[j][2]=e;
    			e=a[i][1];
    			a[i][1]=a[j][1];
    			a[j][1]=e;
    			e=a[i][3];
    			a[i][3]=a[j][3];
    			a[j][3]=e;
    			i++;
    			j--;
    		}
    	}
    	if(i<r) q1(i,r);
    	if(l<j) q1(l,j);
    }
    void q2(int l,int r)
    {
    	int i=l,j=r,mid=qu[(l+r)/2][1],e;
    	while(i<j)
    	{
    		while(qu[i][1]<mid) i++;
    		while(qu[j][1]>mid) j--;
    		if(i<=j)
    		{
    			e=qu[i][1];
    			qu[i][1]=qu[j][1];
    			qu[j][1]=e;
    			e=qu[i][2];
    			qu[i][2]=qu[j][2];
    			qu[j][2]=e;
    			i++;
    			j--;
    		}
    	}
    	if(i<r) q2(i,r);
    	if(l<j) q2(l,j);
    }
    int zz(int x)
    {
    	if(x==bcj[x]) return x;
    	bcj[x]=zz(bcj[x]);
    	return bcj[x];
    }
    int main()
    {
    	cin>>test;
    	int i,j,k,x,y,l;
    	while(test--)
    	{
    		scanf("%d%d%d",&n,&m,&q);
    		fill(qu[1],qu[1]+5600,0);
    		fill(qu[2],qu[2]+5600,0);
    		for(i=1;i<=n;i++)
    		{
    		    bcj[i]=i;
    		    bl[i]=1;
    		}
    		for(i=1;i<=m;i++)
    		{
    			scanf("%d%d%d",&a[i][1],&a[i][2],&a[i][3]);
    		}
    		for(i=m+1;i<=100000;i++)
    		    a[m+1][1]=a[m+1][2]=a[m+1][3]=200000000;
    		q1(1,m);
    		for(i=1;i<=q;i++)
    		{
    			scanf("%d",&qu[i][1]);
    			qu[i][2]=i;
    		}
    		q2(1,q);
    		j=1;
    		int t=0;//t用来累加
    		for(i=1;i<=q;i++)
    		{
    			while(qu[i][1]>=a[j][3] && j<m)
    			{
    				x=zz(a[j][1]);//找祖宗
    				y=zz(a[j][2]);//找祖宗
    				if(x!=y)
    				{
    					bcj[y]=x;
    					t+=bl[x]*bl[y]*2;
    					bl[x]+=bl[y];
    					bl[y]=0;
    				}
    				j++;
    			}
    			ans[qu[i][2]]=t;
    		}
    		for(i=1;i<=q;i++)
    		{
    		    printf("%d
    ",ans[i]);
    		}
    	}
    }
    
  • 相关阅读:
    并发与并行的区别
    Java 中的JSON 字符串
    java spark list 转为 RDD 转为 dataset 写入表中
    SparkConf和SparkContext
    Java 中清空map
    java JSON的使用和解析
    presto计算日期间隔天数或者小时间隔——date_diff函数使用
    Nginx 负载均衡配置
    Nginx 反向代理配置示例(conf文件配置)
    前端同学 linux常用指令汇总
  • 原文地址:https://www.cnblogs.com/chen1352/p/8992973.html
Copyright © 2020-2023  润新知