题解思路:对于完全图而言,图中每一个点都可以直接到达其他点,题目中又已说明每个完全图中边的权值一样,因此我们可以对每个完全图加一个“超级原点”,最后跑两遍 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 "); else{ cnt=0; printf("%lld ",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(" "); } } }