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.
思路
题目把个点分成了个块,规定每一个块里面的任意两点相互到达的时间都为,现在有两个人,一个从点出发,另一个从点出发,他们要找一个点开会,这个点要满足花费的时间最小。题目问你满足时间花费最小的时间是多少,并且把满足这些时间的所有点输出。
这个题如果给每个块的任意两点都建边的话肯定无用的边会很多,这个题需要一点建图思路,我们对于每一个块,建立一个虚点,让块中每个点都连上自己这个块中建立的虚点,权值就为这个块的,那我从起点跑一遍最短路,从终点跑一遍最短路,只需要找到这些点中最小的时间花费的这个点即可ans = min(ans, max(dis1[i], dis2[i])).
配合快读食用更加
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(a, b) memset(a, b, sizeof(a))
namespace IO //使用的时候先IO::begin()
{ //然后输入时IO::read(x)
const ll MX = 4e7;
char buf[MX];
ll c, sz;
void begin()
{
c = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(ll &t)
{
while (c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9'))
c++;
if (c >= sz)
return false;
bool flag = 0;
if (buf[c] == '-')
flag = 1, c++;
for (t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++)
t = t * 10 + buf[c] - '0';
if (flag)
t = -t;
return true;
}
} // namespace IO
const ll N = 1e6 + 10;
const ll inf = 1e18 + 10;
ll n, m;
ll first[N], tot;
ll dis1[N], vis[N], dis2[N];
struct edge
{
ll v, w, next;
} e[N * 2];
struct node
{
ll id, now;
node() {}
node(ll _id, ll _now)
{
id = _id;
now = _now;
}
bool friend operator<(node a, node b)
{
return a.now > b.now;
}
};
void dijkstra1(ll st)
{
for (ll i = 1; i <= n + m; i++)
{
dis1[i] = inf;
vis[i] = 0;
}
dis1[st] = 0;
priority_queue<node> q;
q.push(node(st, 0));
while (!q.empty())
{
node u = q.top();
q.pop();
if (!vis[u.id])
{
vis[u.id] = 1;
for (ll i = first[u.id]; ~i; i = e[i].next)
{
ll v = e[i].v, w = e[i].w;
if (dis1[u.id] + w < dis1[v])
{
dis1[v] = dis1[u.id] + w;
q.push(node(v, dis1[v]));
}
}
}
}
}
void dijkstra2(ll st)
{
for (ll i = 1; i <= n + m; i++)
{
dis2[i] = inf;
vis[i] = 0;
}
dis2[st] = 0;
priority_queue<node> q;
q.push(node(st, 0));
while (!q.empty())
{
node u = q.top();
q.pop();
if (!vis[u.id])
{
vis[u.id] = 1;
for (ll i = first[u.id]; ~i; i = e[i].next)
{
ll v = e[i].v, w = e[i].w;
if (dis2[u.id] + w < dis2[v])
{
dis2[v] = dis2[u.id] + w;
q.push(node(v, dis2[v]));
}
}
}
}
}
void add_edge(ll u, ll v, ll w)
{
e[tot].v = v, e[tot].w = w;
e[tot].next = first[u];
first[u] = tot++;
}
void init()
{
mem(first, -1);
tot = 0;
}
void solve()
{
ll u, w, x, t;
IO::read(n), IO::read(m);
init();
for (ll i = 1; i <= m; i++)
{
IO::read(w), IO::read(t);
while (t--)
{
IO::read(u);
add_edge(u, n + i, w);
add_edge(n + i, u, w);
}
}
dijkstra1(1);
dijkstra2(n);
ll ans = inf;
for (ll i = 1; i <= n; i++)
{
dis1[i] /= 2;
dis2[i] /= 2;
ans = min(ans, max(dis1[i], dis2[i]));
}
if (ans * 2 == inf)
puts("Evil John");
else
{
printf("%lld\n", ans);
ll flag = 1;
for (ll i = 1; i <= n; i++)
{
if (ans == max(dis1[i], dis2[i]))
{
if (flag)
{
printf("%lld", i);
flag = 0;
}
else
printf(" %lld", i);
}
}
puts("");
}
}
int main()
{
// freopen("in.txt", "r", stdin);
IO::begin();
ll t, q = 1;
IO::read(t);
while (t--)
{
printf("Case #%lld: ", q++);
solve();
}
return 0;
}