您的位置:首页 > 其它

hdu 5521 Meeting【最短路SPFA+建图】

2016-09-28 20:30 477 查看

Meeting

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


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.
 

题目大意:
给你n个点,m个集合,接下来m行,每行第一个数表示权值ti,下一个数si表示这个集合中点的个数,接下来si个点的编号,表示这个集合中的点的编号都是哪些,表示这个集合中的这些点之间的任意两点距离都是ti。

现在有两个人,一个人在1号地点,一个人在n号地点,问两个人相见的最短时间,并且问哪些点可以作为约会见面的地点。

思路:

1、假如现在图是建立好的情况下,解决这个最短时间见面的问题:

①首先以点1为源点,求一遍单源最短路,记录到dis【0】【i】中,再以点n为源点,求一遍单源最短路,记录到dis【1】【i】中。

②枚举n个点,对应维护dis【0】【i】+dis【1】【i】的最小值minn。

③对应dis【0】【i】+dis【1】【i】==minn的点i,顺序输出即可。

2、那么我们来处理建图问题:

①题干中保证了Σsi最大是1e6,那么对应如果我们暴力建边,最多可能建立出来1e12条边出来,显然会超时(当然内存你想开那么大也开不出来)

②那么我们考虑对应每个集合都引入一个点u,将集合中的每个点都连入点u,权值设定为0,然后再将u连入集合中的各个点,权值设定为w。(这样就能保证了集合内的点任意两点间距离为w)。

③这个时候我们建立出来的边的条数就是在合理范围之内的了,那么接下来的任务就是写代码了。

Ac代码:

#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
using namespace std;
#define ll __int64
struct node
{
int from;
int to;
ll w;
int next;
}e[10000400];
int vis[2200040];
int a[2200040];
int head[2200040];
ll dis[3][2200040];
int n,m,cont;
void add(int from,int to,ll w)
{
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
}
void SPFA(int ss,int md)
{
for(int i=1;i<=n+m;i++)dis[md][i]=100000000000000004;
dis[md][ss]=0;
memset(vis,0,sizeof(vis));
queue<int >s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
vis[u]=0;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
ll w=e[i].w;
if(dis[md][v]>dis[md][u]+w)
{
dis[md][v]=dis[md][u]+w;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
}
int main()
{
int t;
int kase=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
cont=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++)
{
ll w;int kk;
scanf("%I64d%d",&w,&kk);
for(int j=0;j<kk;j++)
{
scanf("%d",&a[j]);
add(a[j],i+n,0);
add(i+n,a[j],w);
}
}
SPFA(1,0);
SPFA(n,1);
printf("Case #%d: ",++kase);
if(dis[0]
==100000000000000004)
{
printf("Evil John\n");continue;
}
ll ans=100000000000000004;
for(int i=2;i<n;i++)
{
ans=min(ans,max(dis[0][i],dis[1][i]));
}
printf("%I64d\n",ans);
int f=0;
for(int i=1;i<=n;i++)
{
if(ans==max(dis[0][i],dis[1][i]))
{
if(f==0)printf("%d",i);
else printf(" %d",i);
f++;
}
}
printf("\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu 5521 杭电 5521