hdu-6166(最短路+二进制分组)
题意:给你n个点m条边的有向图,然后再给你k个不同的点,问你这k个点的最小距离;
解题思路:这道题最需要注意的就是k个点一定是不同的,那么有一个结论就是任意两个不同的数字中,在他们的二进制地表示中,一定有一位是不同的,这样,我们就可以按照这个规律,把这些数字分成两组,按他们的二进制在某一位是0或者1分组,然后对每一位都跑一次最短路,这里的数据的二进制不超过20位
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 100500
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int num;
int dist;
node(int _num=0,int _dist=0):num(_num),dist(_dist){}
friend bool operator<(node a,node b)
{
return a.dist>b.dist;
}
};
struct Edge
{
int next;
int to;
int fa;
int w;
}edge[maxn];
int head[maxn];
int dist[maxn];
int cnt;
int visit[maxn];
int flag[maxn];
int n,m;
int k,x,y,w,t;
int pow(int u)
{
int x=1;
for(int i=1;i<=u;i++)
x=x*2;
return x;
}
void add(int u,int v,int w)
{
edge[cnt].next=head[u];edge[cnt].w=w;
edge[cnt].to=v;edge[cnt].fa=u;head[u]=cnt++;
}
void dij()
{
memset(dist,inf,sizeof(dist));
priority_queue<node>q;
for(int i=1;i<=n;i++)
{
if(flag[i]==1)
{
q.push(node(i,0));dist[i]=0;
}
}
while(!q.empty())
{
node now=q.top();q.pop();
x=now.num;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(dist[v]>dist[x]+edge[i].w)
{
dist[v]=edge[i].w+dist[x];
q.push(node(v,dist[v]));
}
}
}
}
int main()
{
int tt;
int temp;
int cot=0;
scanf("%d",&tt);
while(tt--)
{
cot++;
//memset(flag,0,sizeof(flag));
memset(visit,0,sizeof(visit));
memset(head,-1,sizeof(head));
cnt=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
}
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
scanf("%d",&t);
visit[t]=1;
}
int ans=inf;
for(int i=0;i<20;i++)
{
for(int j=1;j<=n;j++)
{
if(!visit[j])
continue;
temp=pow(i);flag[j]=0;
if((j&temp)==0)
{
flag[j]=1;
}
else
flag[j]=-1;
}
dij();
for(int j=1;j<=n;j++)
{
if(!visit[j])
continue;
if(flag[j]==-1)
ans=min(ans,dist[j]);
}
for(int j=1;j<=n;j++)
{
if(!visit[j])
continue;
temp=pow(i);flag[j]=0;
if((j&temp)==0)
{
flag[j]=-1;
}
else
flag[j]=1;
}
dij();
for(int j=1;j<=n;j++)
{
if(!visit[j])
continue;
if(flag[j]==-1)
ans=min(ans,dist[j]);
}
}
printf("Case #%d: %d\n",cot,ans);
}
}
,每一位分别跑两次最短路,一次是所有的0到所有的1,另一次是所有的1到所有的0,一共是四十次不到,如果根据每次给的n来跑,会更小。
ps:这里的最短路是多源多汇的;
代码:
hdu-6166(最短路+二进制分组)的更多相关文章
- HDU 6166 Senior Pan(二进制分组+最短路)
题意 给出一个\(n\)个点\(m\)条边的有向图\((n,m<=100000)\),从中选择\(k\)个点\((k<=n)\),问这k个点两两之间的最短路最小值是多少? 思路 直接的想法 ...
- HDU 6166 Senior Pan 二进制分组 + 迪杰斯特拉算法
Senior Pan Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Probl ...
- HDU - 6166:Senior Pan(顶点集合最短路&二进制分组)
Senior Pan fails in his discrete math exam again. So he asks Master ZKC to give him graph theory pro ...
- [bzoj4398] 福慧双修 最短路 二进制分组
---题面--- 题解: 考场上看的这道题,,,当时70分算法打挂了,今天才知道这个也是原题.... 首先,对于不跟1相邻的边,肯定不会经过两次,因为经过两次就回来了,除了增加路径长度之外没有任何意义 ...
- bzoj#2407-探险【最短路,二进制分组】
正题 题目链接:https://darkbzoj.tk/problem/2407 题目大意 \(n\)个点的一张无向图(但是正反权值不同),求一个从\(1\)出发回到\(1\)且不经过重复边的最短路径 ...
- hdu 6166 Senior Pan
http://acm.hdu.edu.cn/showproblem.php?pid=6166 题意: 给出一张无向图,给定k个特殊点 求这k个特殊点两两之间的最短路 二进制分组 枚举一位二进制位 这一 ...
- HDU 6166 Senior Pan(多校第九场 二进制分组最短路)
题意:给出n个点和m条有向边(有向边!!!!我还以为是无向查了半天),然后给出K个点,问这k个点中最近的两点的距离 思路:比赛时以为有询问,就直接丢了,然后这题感觉思路很棒,加入把所有点分成起点和终点 ...
- bzoj 4398 福慧双修——二进制分组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4398 如果枚举1号点走哪些点出去,就从那些点出发跑多源最短路即可.最短路不会重复经过一条边. ...
- 题解 bzoj 4398福慧双修(二进制分组)
二进制分组,算个小技巧 bzoj 4398福慧双修 给一张图,同一条边不同方向权值不同,一条边只能走一次,求从1号点出发再回到1号点的最短路 一开始没注意一条边只能走一次这个限制,打了个从一号点相邻节 ...
随机推荐
- Spring Boot 之使用 Json 详解
Spring Boot 之使用 Json 详解 简介 Spring Boot 支持的 Json 库 Spring Web 中的序列化.反序列化 指定类的 Json 序列化.反序列化 @JsonTest ...
- 深入理解Java中的反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- Python遇到问题总结
1.list的集合 循环删除一个list数据时,会遇到一丢丢问题,详情看Python的list循环遍历中,删除数据的正确方法 但是,里面说的要反转一下list集合,可以用a[::-1]这种方法. &g ...
- 第十二届湖南省赛 A - 2016 ( 数学,同余转换)
给出正整数 n 和 m,统计满足以下条件的正整数对 (a,b) 的数量: 1. 1≤a≤n,1≤b≤m; 2. a×b 是 2016 的倍数. Input 输入包含不超过 30 ...
- 一些Cassandra+YCSB异常
这两天一直在用YCSB.昨天还可以用的YCSB,今天在测试Cassandra时遇到问题了. 环境是在公用局域网的一台debian机器,YCSB和Cassandra都在这台机器上.异常是开始运行YCSB ...
- Linux 典型应用之缓存服务
memcached 安装和简单使用 yum install memcached 启动 -d 表示以守护进程的方式启动 memcached -d 安装telnet 它可以检测某个端口是否是通的,可以发送 ...
- linux系统下MySQL表名区分大小写问题
linux系统下MySQL表名区分大小写问题 https://www.cnblogs.com/jun1019/p/7073227.html [mysqld] lower_case_table_name ...
- symfony框架
Symfony是一个完整的框架结构,设计用来帮助并加速网络应用的开发. 1)安装 symfony的安装还是比较简单的,而且提供了多种安装的方式,详情可以看官网手册 问题: cURL error 60: ...
- vue组件封装选项卡
<template> <myMenu :arr='arr' :arrcontent='content'></myMenu> </template> &l ...
- laravel创建项目
composer create-project --prefer-dist laravel/laravel=5.5.* blog