题意:给出n个点和m条有向边(有向边!!!!我还以为是无向查了半天),然后给出K个点,问这k个点中最近的两点的距离

思路:比赛时以为有询问,就直接丢了,然后这题感觉思路很棒,加入把所有点分成起点和终点两部分,然后加个S点和T点与他们

的距离为0,然后跑最短路就可以了,但是这样有可能最近的两个点都在起点或者都在终点,那么就不一定是最短的,所以就有个二进制分组。

考虑每个点的编号的二进制表示,那么对于任何两个点,他们至少有一位二进制不同,那么我们通过枚举二进制的位,当前位为1的作为起点集合,

当前位为2的作为终点集合,通过这样分组,我们就可以确定至少有一次分组任意两点分别在起点和终点。

复杂度O(20*nlogm)

代码:

/** @xigua */
#include <cstdio>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <cstring>
#include <queue>
#include <set>
#include <string>
#include <map>
#include <climits>
#define PI acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int INF = 1e8 + 5;
const ll inf = 1e15 + 5;
const db eps = 1e-5;
int cnt, head[maxn]; ll dis[maxn];
struct Edge {
int v, next; ll w; //记住这里改顺序下面push进队一定要改!
bool operator < (const Edge &rhs) const {
return w > rhs.w;
}
} e[maxn<<2]; void add(int u, int v, int co) {
e[cnt].v = v;
e[cnt].w = co;
e[cnt].next = head[u];
head[u] = cnt++;
} void init() {
cnt = 0;
memset(head, -1, sizeof(head));
} void dij(int s, int len) {
priority_queue<Edge> pq;
for (int i = 1; i <= len; i++)
dis[i] = inf;
bool vis[maxn] = {0};
dis[s] = 0;
pq.push((Edge){s, 0, 0});
while (!pq.empty()) {
Edge tmp = pq.top(); pq.pop();
if (vis[tmp.v]) continue;
vis[tmp.v] = 1;
for (int i = head[tmp.v]; ~i; i = e[i].next) {
Edge u = e[i];
if (dis[u.v] > dis[tmp.v] + u.w) {
dis[u.v] = dis[tmp.v] + u.w;
pq.push((Edge){u.v, 0, dis[u.v]});
}
}
}
}
int a[maxn];
int u[maxn], v[maxn], w[maxn]; void solve() {
int n, m; cin >> n >> m;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", u + i, v + i, w + i);
}
int k; cin >> k;
for (int i = 1; i <= k; i++) {
scanf("%d", a + i);
}
ll ans = inf;
for (int i = 0; i < 20; i++) {
init();
for (int j = 1; j <= m; j++) {
add(u[j], v[j], w[j]);
// add(v[j], u[j], w[j]);
}
for (int j = 1; j <= k; j++) {
if ((1<<i) & j) {
add(0, a[j], 0);
}
else {
add(a[j], n+1, 0);
}
}
dij(0, n + 10);
ans = min(ans, dis[n+1]);
init();
for (int j = 1; j <= m; j++) {
add(u[j], v[j], w[j]);
// add(v[j], u[j], w[j]);
}
for (int j = 1; j <= k; j++) {
if (((1<<i) & j) == 0) {
add(0, a[j], 0);
}
else {
add(a[j], n+1, 0);
}
}
dij(0, n + 10);
ans = min(ans, dis[n+1]);
}
cout << ans << endl;
} int main() {
int t = 1, cas = 1;
// freopen("in.txt", "r", stdin);
// freopen("in.txt", "w", stdout);
// init();
scanf("%d", &t);
while(t--) {
printf("Case #%d: ", cas++);
solve();
}
return 0;
}

  

HDU 6166 Senior Pan(多校第九场 二进制分组最短路)的更多相关文章

  1. hdu 6166 Senior Pan

    http://acm.hdu.edu.cn/showproblem.php?pid=6166 题意: 给出一张无向图,给定k个特殊点 求这k个特殊点两两之间的最短路 二进制分组 枚举一位二进制位 这一 ...

  2. HDU 6166 Senior Pan (最短路变形)

    题目链接 Problem Description Senior Pan fails in his discrete math exam again. So he asks Master ZKC to ...

  3. HDU 6166.Senior Pan()-最短路(Dijkstra添加超源点、超汇点)+二进制划分集合 (2017 Multi-University Training Contest - Team 9 1006)

    学长好久之前讲的,本来好久好久之前就要写题解的,一直都没写,懒死_(:з」∠)_ Senior Pan Time Limit: 12000/6000 MS (Java/Others)    Memor ...

  4. HDU 6166 Senior Pan 二进制分组 + 迪杰斯特拉算法

    Senior Pan Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Probl ...

  5. 2017多校第9场 HDU 6166 Senior Pan 堆优化Dij

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6166 题意:给你一个有向图,然后给你k个点,求其中一个点到另一个点的距离的最小值. 解法:枚举二进制位 ...

  6. HDU 6166 Senior Pan(k点中最小两点间距离)题解

    题意:n个点,m条有向边,指定k个点,问你其中最近的两点距离为多少 思路:这题的思路很巧妙,如果我们直接枚举两点做最短路那就要做C(k,2)次.但是我们换个思路,我们把k个点按照二进制每一位的0和1分 ...

  7. HDU 6166 Senior Pan(二进制分组+最短路)

    题意 给出一个\(n\)个点\(m\)条边的有向图\((n,m<=100000)\),从中选择\(k\)个点\((k<=n)\),问这k个点两两之间的最短路最小值是多少? 思路 直接的想法 ...

  8. 2018 Multi-University Training Contest 9 杭电多校第九场 (有坑待补)

    咕咕咕了太久  多校博客直接从第三场跳到了第九场orz 见谅见谅(会补的!) 明明最后看下来是dp场 但是硬生生被我们做成了组合数专场…… 听说jls把我们用组合数做的题都用dp来了遍 这里只放了用组 ...

  9. hdu 6169 Senior PanⅡ Miller_Rabin素数测试+容斥

    Senior PanⅡ Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) Pr ...

随机推荐

  1. python使用xlrd操作Excel文件

    一.xlrd读取Excel文件 用xlrd进行读取比较方便,流程和平常手动操作Excel一样,打开工作簿(Workbook),选择工作表(sheets),然后操作单元格(cell). 例子:要打开当前 ...

  2. DOM学习笔记(一)DOM树

    DOM 定义了访问和操作 HTML 文档的标准方法. HTML 文档中的所有内容都是节点,将 HTML 文档表达为树结构,称为节点树 HTML DOM 树 HTML DOM 是关于如何获取.修改.添加 ...

  3. 算法学习--Day10

    今天开始了新一章的学习,前面的题目虽然做了几道,但是我觉得训练量仍然太小了.不过机试确实很多题目,并且难度也有所不同,所以要针对不同的题目进行专门的练习才好.题目类型有些多,等接下来我将搜索的题目写完 ...

  4. hdoj 1588 学好线代与数学

    按部就班,超级简单,虽然不是一次过的...错在那个long long数据问题还是要注意..也不知道要怎么注意:还是说题目吧... 思路看main函数 其他函数功能也是非常有用!代码比较丑...见谅 # ...

  5. layui icon样式1到7

    1: 2: 3: 4: 5: 6: 7:

  6. js 点击往div里添加图片(实例)

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...

  7. unity调android ios 浏览器 uniwebview2.1使用

    uniwebview2.1使用 插件下载地址: http://download.csdn.net/detail/onafioo/9576200 示例 public class BrowserMgr { ...

  8. [Xcode 实际操作]八、网络与多线程-(9)使用异步Get方式获取网页源码

    目录:[Swift]Xcode实际操作 本文将演示如何通过Get请求方式,异步获取网页源码. 异步请求与同步请求相比,不会阻塞程序的主线程,而会建立一个新的线程. 在项目导航区,打开视图控制器的代码文 ...

  9. 阿里云物联网 .NET Core 客户端 | CZGL.AliIoTClient:3. 订阅Topic与响应Topic

    文档目录: 说明 1. 连接阿里云物联网 2. IoT 客户端 3. 订阅Topic与响应Topic 4. 设备上报属性 4.1 上报位置信息 5. 设置设备属性 6. 设备事件上报 7. 服务调用 ...

  10. 为GitHub项目添加协议

    解决方法 如果一开始在GitHub上创建仓库时没有添加协议,可以用以下方式来重新添加相关的协议: 打开GitHub上的某个仓库,点击Create new file: 在新建文件的页面上,输入文件名LI ...