题目:http://acm.hdu.edu.cn/showproblem.php?pid=5521
题意:两个人分别从1和n的城市出发,要求在途中的一个城市相遇并且在该城市开会,求所需要的最短时间,不一定要同时到达,可以一个人在一所城市等着另一个人,要求输出所有满足最小时间的最终开会城市。
输入说明:输入t表示有多少组样例
输入n,m表示有多少城市n,接下来m行输入,分别代表第一个数字表示距离,接下来输入一个数字表示有多少个城市间距离为该距离,接下来输入城市的标号,输入的城市间距离都为第一个输入的值;
题解:利用优化的Dijkstra算法计算最短路径,o(elog(e)),同时根据题意,属于每个距离集的城市间只要做一次松弛操作,因为无论做多少次,通过该路径到达的最短,这里想比的是同一集中的,如 2,3,4都在距离集5中,则从4出发直接到2是5,从4出发经过3再到2是10,这样的是无需经过的步骤,所以只要经过一次松弛操作就可以保证该集合中的所有点都满足条件了
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<vector>
#include<utility>
#define N 100050
#define MAX 0x3f3f3f3f3f3f3f3f
using namespace std;
vector<int> head_p[100500];
vector<int> s[1000050];
int value[1000050];
long long dis[2][N];
bool vis[N];
bool visset[N];
/*void spfa(int p,int start,int v)
{
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(start);
for(int i=1;i<=v;i++)
{
if(i!=start) dis[p][i]=MAX;
else dis[p][i]=0;
}
while(!q.empty())
{
int pos=q.front();q.pop();
for(int i=0;i<head_p[pos].size();i++)
{
int v=head_p[pos][i];
for(int j=0;j<s[v].size();j++){
if(s[v][j]==pos) continue;
if(value[v]+dis[p][pos]<dis[p][s[v][j]])
{
dis[p][s[v][j]]=value[v]+dis[p][pos];
if(!vis[s[v][j]]) {q.push(s[v][j]);vis[s[v][j]]=1;}
}
}
}
vis[pos]=0;
}
}*/
struct Heap
{
int d,u;
bool operator < (const Heap &s) const //用优先队列必须定义这个
{
return d > s.d;
}
};
void dijkstra(int p,int start,int n)
{
priority_queue<Heap> q;
for(int i=1;i<=n;i++) dis[p][i]=MAX;
dis[p][start]=0;
memset(vis,0,sizeof(vis));
memset(visset,0,sizeof(visset));
q.push((Heap){0,start});
while(!q.empty())
{
Heap h=q.top();q.pop();
int u=h.u;
if(vis[u]) continue;
vis[u]=true;
for(int i=0;i<head_p[u].size();i++)
{
int py=head_p[u][i];
if(visset[py]) continue;//优化的重点
visset[py]=true;
for(int j=0;j<s[py].size();j++){
if(u==s[py][j]) continue;
if(dis[p][s[py][j]]>dis[p][u]+value[py])
{
dis[p][s[py][j]]=dis[p][u]+value[py];q.push((Heap){dis[p][s[py][j]],s[py][j]});
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
for(int op=1;op<=t;op++)
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
head_p[i].clear();
}
for(int i=0;i<m;i++) s[i].clear();
for(int i=0;i<m;i++)
{
int pt,m_p;
scanf("%d %d",&value[i],&m_p);
for(int j=1;j<=m_p;j++)
{
int now;
scanf("%d",&now);
s[i].push_back(now);
head_p[now].push_back(i);
}
}
dijkstra(0,1,n);
dijkstra(1,n,n);
long long minn_1=MAX;
for(int i=1;i<=n;i++)
minn_1=min(minn_1,max(dis[0][i],dis[1][i]));
if(minn_1 == MAX ){printf("Case #%d: Evil John\n",op);continue;}
else
{
printf("Case #%d: %lld\n",op,minn_1);
bool flag=false;
for(int i=1;i<=n;i++)
{
if(minn_1==max(dis[0][i],dis[1][i]))
{
if(flag) printf(" ");
printf("%d",i);
flag=true;
}
}
printf("\n");
}
}
return 0;
}