题意

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

思路

直接的想法是对于每个点求一遍最短路,这样一共要跑n次最短路,时间复杂度\(O(nmlogm)\)。

考虑两个点集\(S1\)和\(S2\)之间的最短路,我们可以跑一次最短路求出来。

具体可以新建虚拟源点\(s\)和虚拟汇点\(t\),\(s\)和\(S1\)的每个点之间连一条零边,\(t\)同理。

那么这一次最短路就相当与求出了\(|S1|\times |S2|\)对关系之间的最短路最小值。

通过二进制分组,我们完全可以使复杂度优化到\(O(mlogmlogn)\)。

枚举顶点标号的二进制的每一位,如果这一位为\(1\),那么把这个点分到\(S1\),否则分到\(S2\)。

由于是有向边,还需要反过来求一遍。

代码

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-3
# define MOD 100000007
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int N=100005;
//Code begin... struct qnode{
int v;
LL c;
qnode(int _v=0, LL _c=0):v(_v),c(_c){}
bool operator <(const qnode &r)const{return c>r.c;}
};
struct Edge{int p, next, w;}edge[N<<1];
struct Node{int u, v, w;}node[N];
int head[N], cnt=1, id[N];
LL dist[N];
bool vis[N];
priority_queue<qnode>que;
const int P=16; void add_edge(int u, int v, int w){
edge[cnt].p=v; edge[cnt].next=head[u];
edge[cnt].w=w; head[u]=cnt++;
}
void init(){mem(head,0); cnt=1;}
void Dijkstra(int n, int start){
mem(vis,false); FOR(i,0,n) dist[i]=(LL)1<<60;
dist[start]=0; que.push(qnode(start,0));
qnode tmp;
while (!que.empty()) {
tmp=que.top(); que.pop();
int u=tmp.v;
if (vis[u]) continue;
vis[u]=true;
for (int i=head[u]; i; i=edge[i].next) {
int v=edge[i].p, cost=edge[i].w;
if (!vis[v]&&dist[v]>dist[u]+cost) {
dist[v]=dist[u]+cost;
que.push(qnode(v,dist[v]));
}
}
}
}
int main ()
{
int T, n, m, u, v, w, s, t, K;
scanf("%d",&T);
FOR(cas,1,T) {
LL ans=(LL)1<<60;
scanf("%d%d",&n,&m); s=0; t=n+1;
FOR(i,1,m) scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].w);
scanf("%d",&K);
FOR(i,1,K) scanf("%d",id+i);
FOR(i,0,P) {
init();
FOR(j,1,m) add_edge(node[j].u,node[j].v,node[j].w);
FOR(j,1,K) {
if ((id[j]>>i)&1) add_edge(s,id[j],0);
else add_edge(id[j],t,0);
}
if (!head[s]) continue;
Dijkstra(t,s);
ans=min(ans,dist[t]);
}
FOR(i,0,P) {
init();
FOR(j,1,m) add_edge(node[j].u,node[j].v,node[j].w);
FOR(j,1,K) {
if ((id[j]>>i)&1) add_edge(id[j],t,0);
else add_edge(s,id[j],0);
}
if (!head[s]) continue;
Dijkstra(t,s);
ans=min(ans,dist[t]);
}
printf("Case #%d: %lld\n",cas,ans);
}
return 0;
}

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

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

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

  2. HDU 6166 Senior Pan(多校第九场 二进制分组最短路)

    题意:给出n个点和m条有向边(有向边!!!!我还以为是无向查了半天),然后给出K个点,问这k个点中最近的两点的距离 思路:比赛时以为有询问,就直接丢了,然后这题感觉思路很棒,加入把所有点分成起点和终点 ...

  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 (最短路变形)

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

  5. hdu 6166 Senior Pan

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

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

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

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

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

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

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

  9. 2017多校第9场 HDU 6169 Senior PanⅡ 数论,DP,爆搜

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6169 题意:给了区间L,R,求[L,R]区间所有满足其最小质数因子为k的数的和. 解法: 我看了这篇b ...

随机推荐

  1. Tomcat学习(一)------部署Web应用方法总结

    Tomcat部署Web应用方法总结 在Tomcat中部署Java Web应用程序有两种方式:静态部署和动态部署. 在下文中$CATALINA_HOME指的是Tomcat根目录. 一.静态部署 静态部署 ...

  2. 180804-Spring之动态注册bean

    Spring之动态注册bean 什么场景下,需要主动向Spring容器注册bean呢? 如我之前做个的一个支持扫表的基础平台,使用者只需要添加基础配置 + Groovy任务,就可以丢到这个平台上面来运 ...

  3. Python中remove,pop,del的区别

    先上题:写出最终打印的结果 a = [1, 2, 3, 4] for x in a: a.remove(x) print(a) print("=" * 20) b = [1, 2, ...

  4. Spring入门学习笔记(4)——JDBC的使用

    目录 Spring JDBC框架概览 JdbcTemplate类 配置数据源 数据访问对象(Data Access Object,DAO) 执行SQL命令 Spring JDBC框架概览 使用传统的J ...

  5. Windows10子系统安装ubuntu+kali渗透环境

    Windows10安装子系统ubuntu,安装完ubuntu后再安装katoolin才能使用kali. (katoolin渗透测试的Linux发行版,它可以让你在其他Linux发行版上使用Kali的全 ...

  6. python3 通过qq邮箱定时发送邮件

    下面的代码为了每天定时发送监控邮件,监控什么呢?监控当天redis队列中是否有没有消费的数据,和当天mysql中新增的数据量 # -*- coding:utf-8 -*- from common.re ...

  7. js 的filter()方法

    filter()方法使用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组. filter()基本语法: arr.filter(callback[, thisArg]) filter() ...

  8. VS AI 手写数字识别应用

    看过我上一篇文章的朋友应该知道,我用VS训练出了minst模型.output目录中有.pb文件. 关于.pb文件的介绍见[参考链接] (https://stackoverflow.com/questi ...

  9. Alpha版本BUG BASH

    在本次软件开发的第一轮迭代中,我们团队遇到了很多问题.首先是和学长联系不上导致拿到项目前一版本的代码的时间延后了一个星期. 拿到代码后发现由于安装环境的问题代码无法移植.在这一阶段我们就耗费了大量的时 ...

  10. 团队博客作业Week3 --- 项目选择&&需求疑问

    项目选择 经过团队内所有成员一致探讨,我们团队选择完善和改进之学霸系统的第二个子模块,即:网站内容结构定义和数据处理.具体的要求如下:(摘自Xueba系统项目需求) 网站内容结构定义和数据处理(Con ...