Travel(HDU 5441 2015长春区域赛 带权并查集)
2016-02-04 17:33
417 查看
Travel
Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2404 Accepted Submission(s): 842
[align=left]Problem Description[/align]
Jack likes to travel around the world, but he doesn’t like to wait. Now, he is traveling in the Undirected Kingdom. There are n cities and m bidirectional roads connecting the cities. Jack hates waiting too long on the bus, but he can rest at every city. Jack can only stand staying on the bus for a limited time and will go berserk after that. Assuming you know the time it takes to go from one city to another and that the time Jack can stand staying on a bus is x minutes, how many pairs of city (a,b) are there that Jack can travel from city a to b without going berserk?
[align=left]Input[/align]
The first line contains one integer T,T≤5, which represents the number of test case.
For each test case, the first line consists of three integers n,m and q where n≤20000,m≤100000,q≤5000. The Undirected Kingdom has n cities and mbidirectional roads, and there are q queries.
Each of the following m lines consists of three integers a,b and d where a,b∈{1,...,n} and d≤100000. It takes Jack d minutes to travel from city a to city b and vice versa.
Then q lines follow. Each of them is a query consisting of an integer x where x is the time limit before Jack goes berserk.
[align=left]Output[/align]
You should print q lines for each test case. Each of them contains one integer as the number of pair of cities (a,b) which Jack may travel from a to b within the time limit x.
Note that (a,b) and (b,a) are counted as different pairs and a and b must be different cities.
[align=left]Sample Input[/align]
1
5 5 3
2 3 6334
1 5 15724
3 5 5705
4 3 12382
1 3 21726
6000
10000
13000
[align=left]Sample Output[/align]
2
6
12
新方法,带权的并查集,在并查集集合里面根节点记录了该树的节点个数num,我们每次都把下标较小的点作为根节点。
题目大意:
给定n个城市,以及m条城市之间的道路。每条道路都有一个权值val,给定一个q,求用到所有边权不大于这个值的的情况下,能够互相到达的点对的个数。
思路:
对边权值,询问值q排序从小到大,然后将小于q的边的两端点合并,下标小的点设为根节点,记录树的规模。
每次合并,ans+=2*num[u]*num[v];
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #define Max 20000+5 using namespace std; struct edge { int s,e,val; }a[100000+5]; struct ques { int d,id,res; }p[5005]; int per[Max],num[Max]; int n,m,q; bool cmp(ques a,ques b) { return a.d<=b.d; } bool cmp1(ques a,ques b) { return a.id<b.id; } void init() { for(int i=0;i<=n;i++) { per[i]=i; num[i]=1; } for(int i=0;i<=q;i++) p[i].res=0; } int find(int x) { if(x==per[x]) return x; return per[x]=find(per[x]); } int unite(int a,int b) { a=find(a); b=find(b); if(a<b) //a最大 swap(a,b); per[a]=b; //根节点下标最小,记录树的节点个数 num[b]+=num[a]; return 0; } bool cmp2(edge a,edge b) { return a.val<b.val; } int main() { int T; int i,j; freopen("in.txt","r",stdin); scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&q); init(); for(i=0;i<m;i++) scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].val); for(i=0;i<q;i++) { scanf("%d",&p[i].d); p[i].id=i; } sort(a,a+m,cmp2); sort(p,p+q,cmp); j=0; int t1,t2,ans=0; for(i=0;i<q;i++) { while(j<m&&a[j].val<=p[i].d) { t1=find(a[j].s); t2=find(a[j].e); j++; if(t1!=t2) { ans+=2*num[t1]*num[t2]; unite(t1,t2); } } p[i].res=ans; } sort(p,p+q,cmp1); for(i=0;i<q;i++) printf("%d\n",p[i].res); } }
相关文章推荐
- 短信设备常用AT指令集
- Python脚本
- Pinterest的Feed架构与算法
- 网站反爬虫
- mac下安装使用redis
- 6.MVC框架开发(文件上传)
- //再回调里面调用lanuma表达式 this指针改变
- 作为前端开发兼任产品专员是一种咋样的体验
- 用XPath精确定位节点元素&selenium使用Xpath定位之完整篇
- Servlet过滤器和监听器
- Spring学习4-面向切面(AOP)之aspectj注解方式
- K3CLOUD自动备份Oracle数据库并删除指定天数前的备份
- django 笔记 搭建多个不同版本的开发环境
- hdu1097
- KindEditor 添加默认提示信息
- Java序列化与反序列化
- Java集合类总结 (四)
- Spring学习4-面向切面(AOP)之schema配置方式
- excel
- C++实现查找二叉树中和为某一值的所有路径的示例