HDU 5441 Travel(求各个集合里的秩能组合多少对,只能在一个集合里组合)
来源:互联网 发布:短信群发软件下载 编辑:程序博客网 时间:2024/05/21 17:51
题目地址:点击打开链接
题意:每2个城市间有一个权值,还有每次询问会给一个权值,城市间的权值小于询问的权值即可以走,问某个人能走多少对城市,注意(a,b),(b,a)算一对不同的城市
思路:刚开始用数组存储点和点的距离,然后每次搜强连通分量,搜出来强连通分量的个数不就是每个集合里面的个数么,假如说一个集合里面有n个值,那么总共有n(n-1)对,好理解吧,每个城市和其余城市连一次,不用除以2,因为(a,b),(b,a)算一对不同的城市,(可怜的我刚开始脑残,还还搞个函数求2C(n,2)的值,其实就是A(n,2),我擦),没想到直接MLE了,数组太大了,只能开数组保存每条边的信息,最后搞得太复杂,测试数据没过
下来看别人用并查集顿时傻逼了,我搜索也不就是为了求集合个数么,直接并查集不就搞定了,高兴的太早了,又T了好几次,对时间卡的特别严,在代码里细细分析
错误代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cstring>#include <climits>#include <cmath>using namespace std;int map1[20010][20010];int visit[20010];int n,maxq;int dfs(int x){ visit[x] = 1; int i,sum = 0; for(i=1; i<=n; i++) { if(map1[x][i] < maxq && !visit[i]) { sum++; sum += dfs(i); } } return sum;}int main(){ int t,m,q; int a,b,c,l; int i,j,max1; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&q); for(i=1; i<=n; i++) { for(j=1; j<=n; j++) { map1[i][j] = INT_MAX; } } for(i=0; i<m; i++) { scanf("%d%d%d",&a,&b,&c); map1[a][b] = c; map1[b][a] = c; } for(i=0; i<q; i++) { max1 = 0; memset(visit,0,sizeof(visit)); scanf("%d",&maxq); for(j=1; j<=n; j++) { if(!visit[j]) { l = dfs(j); if(l > max1) max1 = l; } } n = (long long)n; max1 = (long long)max1; printf("%I64d\n",2*myc(max1+1,2)); } } return 0;}
方法是错的,思路也是错的
超时代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cstring>#include <climits>#include <cmath>using namespace std;struct node{ int value; int left; int right; bool operator < (const node &a) const { return value < a.value; }}a[100010];int pre[20010],num[20010];int find(int x){int r = x,i = x,j;while(pre[r] != r){r = pre[r];}while(pre[i] != r)//路径压缩{j = pre[i];pre[i] = r;i = j;}return r;}void join(int x,int y){ int p = find(x);int q = find(y);if(p != q) { pre[p] = q; num[q] += num[p]; }}int main(){ int t,i,j; int n,m,q; int x,y; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&q); for(i=0; i<m; i++) { scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].value); } sort(a,a+m); for(i=0; i<q; i++) { int maxq; scanf("%d",&maxq); for(j=1; j<=n; j++) { pre[j] = j; num[j] = 1; } for(j=0; j<m; j++) { if(a[j].value < maxq) { x = a[j].left; y = a[j].right; join(x,y); } if(a[j].value >= maxq) { break; } } int max1 = 0; for(j=1; j<=n; j++) { if(pre[j] == j) max1 += num[j] * (num[j] - 1); } printf("%d\n",max1); } } return 0;}
这还是优化过的代码第一次都没对每条边的值进行排序
超时代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cstring>#include <climits>#include <cmath>using namespace std;struct node{ int value; int left; int right; bool operator < (const node &a) const { return value < a.value; }} a[100010];struct ask{ int id; int value; bool operator < (const ask &a) const { return value < a.value; }} b[5010];int pre[20010],num[20010];int find(int x){ int r = x,i = x,j; while(pre[r] != r) { r = pre[r]; } while(pre[i] != r)//路径压缩 { j = pre[i]; pre[i] = r; i = j; } return r;}void join(int x,int y){ int p = find(x); int q = find(y); if(p != q) { pre[p] = q; num[q] += num[p]; }}int main(){ int t,i,j; int n,m,q; int x,y; int ans[5010]; scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&q); for(i=0; i<m; i++) { scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].value); } sort(a,a+m); for(j=1; j<=n; j++) { pre[j] = j; num[j] = 1; } for(i=0; i<q; i++) { scanf("%d",&b[i].value); b[i].id = i; } sort(b,b+q); j = 0; for(i=0; i<q; i++) { for(; j<m; j++) { if(a[j].value < b[i].value) { x = a[j].left; y = a[j].right; join(x,y); } if(a[j].value >= b[i].value) { break; } } int max1 = 0; for(j=1; j<=n; j++) { if(pre[j] == j) max1 += num[j] * (num[j] - 1); } ans[b[i].id] = max1; } for(j = 0; j < q; j++) printf("%d\n",ans[j]); } return 0;}
这是第二次优化过的,注意看j=0已经放到了外面
AC代码:
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cstring>#include <climits>#include <cmath>using namespace std;struct edge{ int value; int left; int right; bool operator < (const edge &a) const { return value < a.value; }}a[100010];struct query{ int x,id; bool operator < (const query & a) const { return x < a.x; }}b[5010];int pre[20010],num[20010],paixu[5010];int find(int x){ return pre[x] == x ? x : pre[x] = find(pre[x]);//找老大加路径压缩}/*void join(int x,int y){ int p = find(x);int q = find(y);if(p != q) { pre[p] = q; num[q] += num[p]; }}*///用上面那个join函数其实没有必要void join(int x,int y){ pre[x] = y; num[y] += num[x];}int main(){ int t,i,j; int n,m,q; scanf("%d",&t); while(t--) { int ans = 0; scanf("%d%d%d",&n,&m,&q); for(i=1; i<=n; i++)//记得是从1开始赋值 { pre[i] = i; num[i] = 1; } for(i=0; i<m; i++) { scanf("%d%d%d",&a[i].left,&a[i].right,&a[i].value); } sort(a,a+m); for(i=0; i<q; i++) { scanf("%d",&b[i].x); b[i].id = i; } sort(b,b+q); j = 0;//j就刚开始赋一个0即可 for(i=0; i<q; i++) { while(j<m && a[j].value <= b[i].x)//从上一次退出来的结果上接着搞,节省不少时间,每次从0开始搞也是错的,导致ans出错 { int left = find(a[j].left); int right = find(a[j].right); j++;//j++在前,不然continue退出就不加了 if(left == right) continue; ans += (num[left] + num[right])*(num[left] + num[right] - 1) - num[left] * (num[left] - 1) - num[right] * (num[right] - 1);//每次利用上面的结果递推很巧妙 join(left,right); } paixu[b[i].id] = ans; } for(i=0; i<q; i++) { printf("%d\n",paixu[i]); } } return 0;}
大神地址:点击打开链接
0 0
- HDU 5441 Travel(求各个集合里的秩能组合多少对,只能在一个集合里组合)
- 给定一个值,求组合该值的组合集合
- 一集合指定元素组合的条件,求出集合中有多少对组合,集合的元素不重复使用。
- HDU 5479 Scaena Felix(求一个序列里有多少对括号能够匹配)
- 求集合的组合和排列问题
- 集合的组合问题
- 循环递归求数组里数据的组合
- 求 数组里 和为s的所有组合
- 求从几个集合中各选取一个元素,并组合的算法
- 在java里的集合的知识点
- c#集合在UNITY3D里的应用
- python 里的集合
- 深度优先算法求含有N个元素的集合的全部组合(即:在集合中选1,2,3...N个元素的所有组合,不是排列)
- 利用分治思想,写一个求解从n个元素里选取m个有多少种组合方案的(非递归)高性能算法
- 求能组成一个数的所有组合
- 一个文件里有10万个随机正整数,按照以下规则能组合出一份新的数据
- 把一个数组里的组合全部列出来.
- 把一个数组里的组合全部列出
- Volley, HttpUtils,省略findViewById()和点击事件的.setOnClickListener(this);,DbUtils
- 测试分页接口
- ViewPager与SwipeRefreshLayout冲突问题
- Android之Json转换利器Gson之实例一-简单对象转化和带泛型的List转化
- BZOJ 3684 大朋友与多叉树 多项式求幂/求exp+拉格朗日反演
- HDU 5441 Travel(求各个集合里的秩能组合多少对,只能在一个集合里组合)
- 关于json一片号的文章,转载来收藏一下
- web_custom_request 例子
- 如果浏览器不支持 cookie 该怎么办?
- maven 工程学习
- 【面试】-百度外卖后端开发工程师
- UVA 10269 Adventure of Super Mario 最短路
- 显示win32控制台
- <context:annotation-config />