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. e648. 双击和三击事件

    component.addMouseListener(new MyMouseListener()); public class MyMouseListener extends MouseAdapter ...

  2. RequireJS使用小结1——for Effective JavaScript Module Loading

    1. require和define的区别 The require() function is used to run immediate functionalities, while define() ...

  3. fatal error: malformed or corrupted AST file: &#39;Unable to load module Darwin.pcm 问题解决

    xcode5 编译project.偶然碰到了以下的问题: fatal error: malformed or corrupted AST file: 'Unable to load module &q ...

  4. MySQL 数据库常用命令小结

    MySQL 数据库常用命令 1.MySQL常用命令 create database name; 创建数据库 use databasename; 选择数据库 drop database name 直接删 ...

  5. 在VS中写js的同学注意了。。。。。。。。。。。。。。。。。。。

    在vs中安装扩展jsdoc就可以实现这个功能

  6. php获取QQ头像并显示的方法

    鉴于此,我在想一个大众化的,比较简单的方法,我想到的是对于没有头像的朋友调用其QQ头像, 因为QQ现在至少是人手一个,所以只需要留言时填写QQ号,然后调用其头像,这样一来就方便多了. 首先是获取QQ的 ...

  7. shiro缓存

    shiro的可以权限控制内容包括:URL地址.Web页面的元素.以及方法,即shiro对用户权限的控制是细粒度的.从用户的一次访问来说,他可能需要最多经过三种.多次的验证.这里的多次怎么说呢?如果说W ...

  8. [转]oracle存储过程、声明变量、for循环

    oracle存储过程.声明变量.for循环 1.创建存储过程 create or replace procedure test(var_name_1 in type,var_name_2 out ty ...

  9. optimization blocks (csapp chapter 5.1)

    p_511 编译器在没有指示下,会做‘ safe optimization',因此有些优化在没有参数的指示下是不会对代码做优化的,故在程序中应该避免某一类代码,因为它们妨碍了编译器做优化. optim ...

  10. Linux下的shell编程入门

    通常情况下,我们从命令行输入命令每输入一次就能够得到系统的一次响应.一旦需要我们一个接着一个的输入命令而最后才得到结果的时候,这样的做法显然就没有效率.要达到这样的目的,通常我们利用shell程序或者 ...