Meeting
Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 5333 Accepted Submission(s): 1692
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
2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)
Recommend
wange2014
题意:
这道题就是给了时间t,集合s,然后给了s个数字,代表这几个数字两两间是可以相互到达的,然后相互到达的时间是t。然后一个人在1,另一个人在n,问两个人最短时间见面的点在哪里,如果不存在输出一行字母。
想法:就是多加m个点,类似于

这样。然后这样就可以了。因为dij算法记录的是起始点到每一个点的最短路。
重点是:饶齐的dijsktra板子太慢了,邝斌的板子飞快。
代码1:kuangbin板子(1542ms):
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int MAXN=2000010;
struct qnode
{
int v;
int c;
qnode(int _v=0,int _c=0):v(_v),c(_c) {}
bool operator <(const qnode &r)const
{
return c>r.c;
}
};
struct Edge
{
int v,cost;
Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
};
vector<Edge>E[MAXN];
bool vis[MAXN];
int dist[MAXN];
//点的编号从 1 开始
void Dijkstra(int n,int start)
{
memset(vis,false,sizeof(vis));
for(int i=1; i<=n; i++)dist[i]=INF;
priority_queue<qnode>que;
while(!que.empty())que.pop();
dist[start]=0;
que.push(qnode(start,0));
qnode tmp;
while(!que.empty())
{
tmp=que.top();
que.pop();
int u=tmp.v;
if(vis[u])continue;
vis[u]=true;
for(int i=0; i<E[u].size(); i++)
{
int v=E[tmp.v][i].v;
int cost=E[u][i].cost;
if(!vis[v]&&dist[v]>dist[u]+cost)
{
dist[v]=dist[u]+cost;
que.push(qnode(v,dist[v]));
}
}
}
}
void add(int u,int v,int w)
{
E[u].push_back(Edge(v,w));
}
int a[MAXN],c[MAXN];
int shuchu[MAXN];
int main()
{
int cas=0;
int t,tt,n,m,s,x;
scanf("%d",&tt);
while(tt--){
cas++;
scanf("%d%d",&n,&m);
for(int i=1;i<=n+m;i++)
E[i].clear();
for(int i=1;i<=m;i++)
{
scanf("%d%d",&t,&s);
for(int j=1;j<=s;j++){
scanf("%d",&x);
add(x,i+n,t);
add(i+n,x,0);
}
}
Dijkstra(n+m,1);
for(int i=1;i<=n;i++){
a[i]=dist[i];
}
Dijkstra(n+m,n);
for(int i=1;i<=n;i++){
c[i]=max(a[i],dist[i]);
}
ll minn=INF;
for(int i=1;i<=n;i++){
if(minn>c[i])
minn=c[i];
}
int cnt=0;
printf("Case #%d: ",cas);
if(minn==INF){
printf("Evil John\n");
continue;
}
else{
printf("%d\n",minn);
for(int i=1;i<=n;i++){
if(c[i]==minn)
{shuchu[++cnt]=i;}
}
for(int i=1;i<cnt;i++){
printf("%d ",shuchu[i]);
}
printf("%d\n",shuchu[cnt]);
}
}
return 0;
}
/*
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
*/
代码2:
饶齐板子(2612ms):
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
const int maxn = 2000000;
#define INF 1e18
struct HeapNode //Dijkstra算法用到的优先队列的节点
{
ll d;int u;
HeapNode(ll d,int u):d(d),u(u){}
bool operator < (const HeapNode &rhs)const
{
return d > rhs.d;
}
};
struct Edge //边
{
int from,to;ll dist;
Edge(int f,int t,ll d):from(f),to(t),dist(d){}
};
struct Dijkstra
{
int n,m; //点数和边数,编号都从0开始
vector<Edge> edges; //边列表
vector<int> G[maxn];//每个节点出发的边编号(从0开始编号)
bool done[maxn]; //是否已永久标号
ll d[maxn]; //s到各个点的距离
//int p[maxn]; //p[i]为从起点s到i的最短路中的最后一条边的编号
void init(int n)
{
this->n=n;
for(int i=0;i<n;i++) G[i].clear();//清空邻接表
edges.clear(); //清空边列表
}
void AddEdge(int from,int to,int dist)
{//如果是无向图,每条无向边调用两次AddEdge
edges.push_back(Edge(from,to,dist) );
m = edges.size();
G[from].push_back(m-1);
}
void dijkstra(int s)//求s到所有点的距离
{
priority_queue<HeapNode> Q;
for(int i=0;i<n;i++) d[i]=INF;
d[s]=0;
memset(done,0,sizeof(done));
Q.push(HeapNode(0,s) );
while(!Q.empty())
{
HeapNode x=Q.top(); Q.pop();
int u=x.u;
if(done[u]) continue;
done[u]= true;
int tmpp=G[u].size();
for(int i=0;i<tmpp;i++)
{
Edge& e= edges[G[u][i]];
if(d[e.to]> d[u]+e.dist)
{
d[e.to] = d[u]+e.dist;
//p[e.to] = G[u][i];
Q.push(HeapNode(d[e.to],e.to) );
}
}
}
}
}D1,DN;
int res[100010];
int main()
{
ios::sync_with_stdio(false);
int T,cas=1;
cin>>T;
while(T--)
{
int n,m,i,j,tot=0;
cin>>n>>m;
D1.init(n+m+10);
DN.init(n+m+10);
for(i=0;i<m;i++)
{
ll t;
int s;
cin>>t>>s;
for(j=0;j<s;j++)
{
int x;
cin>>x;
x--;
D1.AddEdge(x,n+i+1,t);
D1.AddEdge(n+i+1,x,0);
DN.AddEdge(x,n+i+1,t);
DN.AddEdge(n+i+1,x,0);
}
}
D1.dijkstra(0);
DN.dijkstra(n-1);
ll minn=INF;
for(i=0;i<n;i++)
{
ll d1,dn;
d1=D1.d[i];
dn=DN.d[i];
minn=min(minn,max(d1,dn));
}
cout<<"Case #"<<cas++<<": ";
if(minn==INF)
{
cout<<"Evil John"<<endl;
continue;
}
else
cout<<minn<<endl;
for(i=0;i<n;i++)
{
ll d1,dn;
d1=D1.d[i];
dn=DN.d[i];
if(max(d1,dn)==minn)
{
res[tot++]=i+1;
}
}
for(i=0;i<tot;i++)
{
if(i==tot-1)
{
cout<<res[i]<<endl;
}
else
{
cout<<res[i]<<" ";
}
}
}
}
本文探讨了一种在特定场景下优化最短路径算法的方法,通过引入额外节点改进Dijkstra算法,实现快速找到两点间的最短会合点。文章对比了两种不同实现方式,展示了优化后的算法如何显著提高效率。
806

被折叠的 条评论
为什么被折叠?



