Meeting

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3704    Accepted Submission(s): 1187

Problem Description
Bessie and her friend Elsie decide to have a meeting. However, after Farmer John decorated his
fences they were separated into different blocks. John's farm are divided into n blocks labelled from 1 to n.
Bessie lives in the first block while Elsie lives in the n-th one. They have a map of the farm
which shows that it takes they ti minutes to travel from a block in Ei to another block
in Ei where Ei (1≤i≤m) is a set of blocks. They want to know how soon they can meet each other
and which block should be chosen to have the meeting.
 
Input
The first line contains an integer T (1≤T≤6), the number of test cases. Then T test cases
follow.

The first line of input contains n and m. 2≤n≤105. The following m lines describe the sets Ei (1≤i≤m). Each line will contain two integers ti(1≤ti≤109) and Si (Si>0) firstly. Then Si integer follows which are the labels of blocks in Ei. It is guaranteed that ∑mi=1Si≤106.

 
Output
For each test case, if they cannot have the meeting, then output "Evil John" (without quotes) in one line.

Otherwise, output two lines. The first line contains an integer, the time it takes for they to meet.
The second line contains the numbers of blocks where they meet. If there are multiple
optional blocks, output all of them in ascending order.

 
Sample Input
2
5 4
1 3 1 2 3
2 2 3 4
10 2 1 5
3 3 3 4 5
3 1
1 2 1 2
 
Sample Output
Case #1: 3
3 4
Case #2: Evil John

Hint

In the first case, it will take Bessie 1 minute travelling to the 3rd block, and it will take Elsie 3 minutes travelling to the 3rd block. It will take Bessie 3 minutes travelling to the 4th block, and it will take Elsie 3 minutes travelling to the 4th block. In the second case, it is impossible for them to meet.

 
Source
 
  • 在路径1->n中取一点使得max(time(1->vex),time(n->vex))最小
  • 很容易考虑从1和n分别跑一遍单源最短路得到两个距离数组dis1和disn,然后逐个比较下就可以了
  • 但是这题难点在于给出结点间关系是以set方式给予的,我们如果不能加速自当前点寻找可达点的查找速度就会tle
  • 每个set看似分离,实际上因为set相交的缘故,在不同set中的两个点是可达的
  • 我们可以先对于单个set考虑,可以通过缩点,对于一个set中的点用一个新的点表示,然后用新点和其他set相连
  • 接下来就是考虑怎样建边使得同一个set中的点之间的距离相同
  • 新加的点不会增加两个点之间的距离,自set中一点到新点不应有距离的增加,那么我们建边的时候set内的点到新点距离为0,新点到set内每一个点的距离都相同
  • 通过这样的缩点和建边就可以将原本的set结构等价转换,我们只需要跑两遍最短路即可
 #include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
typedef long long LL ;
typedef unsigned long long ULL ;
const int maxn = 1e6 + ;
const LL inf = 0x3f3f3f3f3f;
const int npos = - ;
const int mod = 1e9 + ;
const int mxx = + ;
const double eps = 1e- ;
const double PI = acos(-1.0) ; struct node{
LL len;
int i;
bool operator < (const node &r)const{
if(len!=r.len)
return len<r.len;
else
return i<r.i;
}
};
struct enode{
int v;
LL w;
int next;
};
struct qnode{
int u;
LL dis;
bool operator < (const qnode &r)const{
return dis>r.dis;
}
};
enode edge[maxn<<];
int head[maxn<<], cnt;
void addedge(int x, int y, LL z){
edge[cnt]=(enode){y,z,head[x]};
head[x]=cnt++;
}
std::vector< node > buf;
int T, n, m, u, v, s, no1, non;
LL w, dis1[maxn], disn[maxn], ans;
bool vis[maxn];
void DIJ(LL *dis, int source){
LL now;
priority_queue< qnode > Q;
qnode temp;
for(int i=;i<=n+m;i++){
vis[i]=false;
dis[i]=inf;
}
dis[source]=0LL;
Q.push((qnode){source,dis[source]});
while(!Q.empty()){
temp=Q.top();
Q.pop();
if(!vis[temp.u]){
u=temp.u;
now=temp.dis;
vis[u]=true;
for(int i=head[u];i!=-;i=edge[i].next){
v=edge[i].v;
w=edge[i].w;
if(now+w<=dis[v]){
dis[v]=now+w;
Q.push((qnode){v,dis[v]});
}
}
}
}
}
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(~scanf("%d",&T)){
for(int kase=;kase<=T;kase++){
no1=;
non=;
scanf("%d %d",&n,&m);
cnt=;
memset(head,-,sizeof(head));
for(int i=;i<=m;i++){
scanf("%lld %d",&w,&s);
for(int j=;j<=s;j++){
scanf("%d",&u);
if(u==)no1=;
if(u==n)non=;
v=n+i;
addedge(u,v,0LL);
addedge(v,u,w);
}
}
printf("Case #%d: ",kase);
if(!(no1&&non)){
printf("Evil John\n");
continue;
}
DIJ(dis1,);
DIJ(disn,n);
buf.clear();
for(int i=;i<=n;i++)
buf.push_back((node){max(dis1[i],disn[i]),i});
sort(buf.begin(),buf.end());
ans=buf[].len;
if(ans==inf){
printf("Evil John\n");
}else{
printf("%lld\n",ans);
printf("%d",buf[].i);
int i=;
while(i<buf.size() && buf[i].len==ans)
printf(" %d",buf[i++].i);
cout<<endl;
}
}
}
return ;
}

HDU_5521_Meeting的更多相关文章

随机推荐

  1. C++ 程序可以定义为对象的集合

    C++ 基本语法C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互.现在让我们简要地看一下什么是类.对象,方法.即时变量. 对象 - 对象具有状态和行为.例如:一只狗的状态 - 颜色 ...

  2. linux -- ubuntu14.10安装gnome桌面环境和dock工具

    ubuntu14.10系统自带Unity桌面环境,但是还是习惯于gnome桌面环境,再加上dock用着就很顺手了.   方法/步骤 首先,按Ctrl+Alt+T,调出终端.在其中输入:sudo apt ...

  3. CentOS开关机命令

    命令简介 shutdown,poweroff,reboot,halt,init都可以进行关机,大致用法. /sbin/halt     [-n] [-w] [-d] [-f] [-i] [-p] [- ...

  4. 【Java面试题】27 多线程笔试面试概念问答

    第一题:线程的基本概念.线程的基本状态及状态之间的关系? 线程,有时称为轻量级进程,是CPU使用的基本单元:它由线程ID.程序计数器.寄存器集合和堆栈组成.它与属于同一进程的其他线程共享其代码段.数据 ...

  5. Vertex and FragmentShader顶点与片段着色器

    一.顶点与片段着色器简介 Vertex and FragmentShader:最强大的Shader类型,也是本系列的重点,下文中简称V&FShader,属于可编程渲染管线.使用的是CG/HLS ...

  6. C# Serializable(转)

    C# Serializable System.SerializableAttribute 串行化是指存储和获取磁盘文件.内存或其他地方中的对象.在串行化时,所有的实例数据都保存到存储介质上,在取消串行 ...

  7. Linux 内核中 likely 与 unlikely 的宏定义解析

    在 2.6 内核中,随处能够见到 likely() 和 unlikely() 的身影,那么为什么要用它们?它们之间有什么差别? 首先要明白: if(likely(value)) 等价于 if(valu ...

  8. laravel安装 redis 并驱动 session

    1)composer 安装 redis composer require predis/predis 如果感兴趣,可以看一下这里 2)配置 redis 连接(config/database.php 配 ...

  9. 转的:burp suite小例子

    Web安全测试时经常会遇到一些蹩脚的注射点,而因各种原因利用注射又无法获取网站管理账号或拥有网站管理权限却迟迟不能upload一个shell的时候,可能会权衡一下web权限与数据库信息,哪个是我们所需 ...

  10. idea & datagrip 注册码

    CNEKJPQZEX-eyJsaWNlbnNlSWQiOiJDTkVLSlBRWkVYIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...