N个点,M个集合
集合内的点转移花费ti
求在1和n的两个人能不能相见,不能输出-1,能输出最短时间,能相遇的位置
分别从1和n开始跑dijkstra,对于每个点相遇的时间为max(dis1,disn)
对于每个集合建图时建立一个新节点x x到集合到集合内任意一点的距离为ti,集合内到x的距离为0
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<queue>
#include<algorithm>
#define oo 1000000000000000ll
#define fgx printf("-------\n")
using namespace std;
typedef long long ll;
struct EDGE{
int to,nxt;
ll ti;
}ed[1000005*2];
int cnt;
int head[1000005];
struct node{
int x;
ll t;
};
bool operator < (const node &a,const node &b){
return a.t>b.t;
}
void addedge(int u,int v,int ti){
ed[cnt].to=v,ed[cnt].ti=ti,ed[cnt].nxt=head[u],head[u]=cnt++;
}
ll dis[2][1000005];
bool vis[1000005];
priority_queue<node>q;
void dijkstra(int s,int e){
node a,b;
memset(vis,0,sizeof(vis));
a.x=s,a.t=0,dis[e][s]=0;
q.push(a);
while(!q.empty()){
a=q.top();
q.pop();
int u=a.x;
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];~i;i=ed[i].nxt){
int v=ed[i].to;
if(vis[v])continue;
if(dis[e][v]>dis[e][u]+ed[i].ti){
dis[e][v]=dis[e][u]+ed[i].ti;
b.x=v,b.t=dis[e][v];
q.push(b);
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
int ca=1;
while(t--){
memset(head,-1,sizeof(head));
cnt=0;
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n+m;i++)dis[1][i]=dis[0][i]=oo;
for(int i=1;i<=m;i++){
int size;
ll ti;
scanf("%d%d",&ti,&size);
for(int j=1;j<=size;j++){
int x;
scanf("%d",&x);
addedge(i+n,x,ti);
addedge(x,i+n,0);
}
}
dijkstra(1,0);
dijkstra(n,1);
ll ansd=oo;
int num=1;
for(int i=1;i<=n;i++){
// printf("%d %lld %lld\n",i,dis[0][i],dis[1][i]);
dis[0][i]=max(dis[1][i],dis[0][i]);
if(dis[0][i]==ansd)num++;
else if(dis[0][i]<ansd)ansd=dis[0][i],num=1;
}
if(ansd==oo){
printf("Case #%d: Evil John\n",ca++);
continue;
}
printf("Case #%d: %lld\n",ca++,ansd);
for(int i=1;i<=n;i++){
if(dis[0][i]==ansd)
{
printf("%d",i);
if(num>1)printf(" ");
if(!num)break;
num--;
}
}
printf("\n");
}
return 0;
}