题解思路:对于完全图而言,图中每一个点都可以直接到达其他点,题目中又已说明每个完全图中边的权值一样,因此我们可以对每个完全图加一个“超级原点”,最后跑两遍 dijkstra 即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,int> PII;
const int MAXN = 2e5+10;
const double EPS = 1e-12;
int T,n,m,cnt,cas;
ll dis1[MAXN],dis2[MAXN];
int path[MAXN];
struct node{
int to;
ll cost;
};
vector<node>G[MAXN];
void Dij(int s,ll d[]){
for(int i=1;i<=n+m;i++)d[i]=1e18;
d[s]=0;
priority_queue<PII,vector<PII>,greater<PII> >q;
q.push(PII(0,s));
while(!q.empty()){
PII p=q.top();q.pop();
int u=p.second;
if(p.first>d[u])continue;
for(int i=0;i<G[u].size();i++){
node v=G[u][i];
if(d[v.to]>d[u]+v.cost){
d[v.to]=d[u]+v.cost;
q.push(PII(d[v.to],v.to));
}
}
}
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
for(int i=1;i<=n+m;i++)G[i].clear();
int si;ll ti;
for(int i=1;i<=m;i++){
scanf("%lld %d",&ti,&si);
for(int j=1;j<=si;j++){
int x;scanf("%d",&x);
G[n+i].push_back(node{x,ti});
G[x].push_back(node{n+i,ti});
}
}
Dij(1,dis1);
Dij(n,dis2);
ll minn=1e18;
for(int i=1;i<=n;i++)
minn=min(minn,max(dis1[i],dis2[i]));
printf("Case #%d: ",++cas);
if(minn==1e18)printf("Evil John\n");
else{
cnt=0;
printf("%lld\n",minn/2);
for(int i=1;i<=n;i++)
if(minn==max(dis1[i],dis2[i]))
path[++cnt]=i;
for(int i=1;i<=cnt;i++){
printf("%d",path[i]);
if(i!=cnt)printf(" ");
}
printf("\n");
}
}
}