湖南大学ACM程序设计新生杯大赛 - B Build

本文探讨了一个经典的图论问题,即在有限的资金条件下如何构建道路以最大化能够互相连接的城市对的数量。通过类似最小生成树的方法,对边进行排序并使用并查集记录连通情况,实现高效的解决方案。

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 


In country  A, some roads are to be built to connect the cities。However, due to limited funds, only some roads can be built.That is to say,if the limit is 100$, only roads whose cost are no more than 100$ can be built. 

Now give you n cities, m roads and the cost  of each road wi (i=1..m). There are q queries, for each query there is a number k, represent the limit, you need to output the maximum number of pairs of cities that can reach each other.  


输入描述:

The first line consist of two integers, n,m, n the number of cities and m the number of roads. The next m lines , each line has three integers a,b,w, represent that you can bulid a road between city a and city b with cost w.
The next line an integer q, the number of querries. The next q lines each an integer k ,the limit of the fund.
n<10000, m < 10000, k < 10000, q<10000;

输出描述:

For each querry ,you should output the anwser.
示例1

输入

3 2
1 2 1
2 3 2
1
2

输出

3

题意:

给你一些边,每个边都有个代价,每次问一个x,问你用代价<=x的边来建树,能有几个点是互相连接的。


POINT:

就是类似最小生成树。先给边排个序,然后依次记录每条边连完之后的答案。

然后二分搜索答案就行了。


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <math.h>
using namespace std;
#define LL long long
const int maxn = 1e4+55;
const int mod = 2e5+7;
const double eps = 1e-8;
int ans[maxn];
int num[maxn],fa[maxn];
struct node
{
	int l,r,w;
}len[maxn];

bool cmd(node a , node b)
{
	return a.w<b.w;
}
int find(int x)
{
	return fa[x]==x?x:fa[x]=find(fa[x]);
}

int main()
{
	int n,m;scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) fa[i]=i,num[i]=1;
	for(int i=1;i<=m;i++){
		scanf("%d %d %d",&len[i].l,&len[i].r,&len[i].w);
	}
	len[0].w=0;
	sort(len+1,len+1+m,cmd);
	ans[0]=0;
	int now=0;
	for(int i=1;i<=m;i++){
		int x=find(len[i].l);
		int y=find(len[i].r);
		if(y==x){
		}else{
			now+=num[y]*num[x];
			fa[x]=y;
			num[y]+=num[x];
		}
		ans[i]=now;
	}
	int q;scanf("%d",&q);
	while(q--){
		int k;scanf("%d",&k);
		int l=0,r=m;
		while(l<r){
			int mid=(l+r+1)>>1;
			if(len[mid].w<=k){
				l=mid;
			}else{
				r=mid-1;
			}
		}printf("%d\n",ans[l]);


	}

}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值