HDU 6166 Senior Pan
来源:互联网 发布:全国流动人口监测数据 编辑:程序博客网 时间:2024/06/05 05:46
这道题很有意思,方法很有意思,题目要求在一个有向图中,两两之间的点的最短距离,刚开始想的是直接用优先队列模拟那么多个点互相搜索,最早相遇的那一对就是答案,这个方法无向图应该是对的,但是有向图就GG了,相遇并不代表两者可以从一点到另一点是可达的。
正解是类比cf 835E,枚举二进制位按照标号当前位为1 和当前位为0分为两个集合,每次求解两个集合之间的最短路即可覆盖到所有的点对。时间复杂度20*dijstla时间。
怎么说,这个官方题解也是十分抽象的,看了另一种,更加形象化的解释。
首先先要知道两个集合之间的最短路是怎么求得的。这个是前置知识点
然后按照图中的集合选取方式,第一次就求取了蓝色和白色部分蓝色到白色两两之间最短距离是多少,剩下没求取的是蓝色内部和白色内部的关系了。
那么第二次最短路的时候,再按照图中标识的,把是蓝色的全部加入起点,白色的全部是终点,那么就可以求取第一轮中没求的那部分答案了。这样递归下去就能求取所有两两之间关系了。很像线段树那种思想。
剩下要思考的就是怎么找到每一轮最短路的那些蓝色点了。
一共
/************************************************************************* > File Name: d.cpp > Author: MentalOmega > Mail: 965194745@qq.com > Created Time: 2017年8月23日 > function:集合论两两之间的关系 用二分解决 ************************************************************************/#include<bits/stdc++.h>using namespace std;const int MAXN = 100000+10;struct Edge{ int from,to,cost,next;} edge[MAXN*2];int edgecnt=0;int head[MAXN];int n,m;void add_edge(int from,int to,int cost){ edge[edgecnt]= {from,to,cost,head[from]}; head[from]=edgecnt++;}int node[MAXN];bool mark[MAXN]= {0};bool vis[MAXN]= {0};long long dis[MAXN];long long ans = 1e18;int k;void spfa(int len,bool flag){ if(len==1) return ; memset(mark,0,sizeof mark); memset(vis,false,sizeof vis); fill(dis,dis+MAXN,1e18); queue<int> que; for(int i=0; i<k; i++) { if(((i/len)&1)==flag) que.push(node[i]),vis[node[i]]=true,dis[node[i]]=0; else mark[node[i]]=true; } while(que.size()) { int u = que.front(); que.pop(); vis[u]=false; for(int i=head[u]; i!=-1; i=edge[i].next) { int v = edge[i].to; if(dis[v]>dis[u]+edge[i].cost) { dis[v]=dis[u]+edge[i].cost; if(mark[v]) { ans = min(ans,dis[v]); } if(vis[v]==false) { vis[v]=true; que.push(v); } } } } spfa(len/2,flag);}int main(){ if (fopen("in.txt", "r") != NULL) { freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); } int t; cin>>t; int icase=0; while(t--) { ans=1e18; edgecnt=0; memset(head,-1,sizeof head); printf("Case #%d: ",++icase); scanf("%d%d",&n,&m); for(int i=0; i<m; i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add_edge(a,b,c); } scanf("%d",&k); for(int i=0; i<k; i++) scanf("%d",node+i); int len = 1; while(len<k) len<<=1;//长度的选取,要选2的倍数,不然画个图就知道不能覆盖所有两两关系了 spfa(len/2,false); spfa(len/2,true); printf("%lld\n",ans); } return 0;}
阅读全文
0 0
- HDU 6166 Senior Pan
- HDU 6166 Senior Pan
- [HDU 6166] Senior Pan
- HDU 6166 Senior Pan
- hdu-6166 Senior Pan
- HDU 6166 Senior Pan
- HDU 6166 Senior Pan
- HDU-6166 Senior Pan
- hdu 6166 Senior Pan 最短路
- hdu 6166 Senior Pan(巧妙的Dijkstra)
- HDU 6166 Senior Pan (2017多校9
- hdu 6166 Senior Pan(最短路)
- [hdu 6166 Senior Pan]Dijkstra+概率随机
- HDU 6166 Senior Pan [二分+SPFA]
- HDU 6166 Senior Pan(SPFA+二进制分组)
- Senior Pan HDU
- Senior Pan HDU
- Hdu 6166 Senior Pan【思维+随机化+最短路】好题~
- Makefile简单试验
- java 将包放入类中 静态导入 大部分使用的方法都是静态方法
- FastDFS安装配置以及整合Nginx测试
- 【Gym
- 单链表实现
- HDU 6166 Senior Pan
- 浏览器更新HTTP服务器图片并显示
- Servlet(Config、Context)
- (UVA
- OpenStreetMap/Google/百度/Bing瓦片地图服务(TMS)
- Hive学习笔记 --- 查看Table在HDFS中存储的位置
- 作用域安全的构造函数
- TCP_DEFER_ACCEPT
- MySQL 数据类型