挺傻逼的一道题,犯了一些傻逼错误,还写了对拍,拍出了别人的错误。。就是把航线上的每个点对暴力建边,然后跑双关键字最短路即可。。inf要开的够大。。
#include<cstdio>
#include<iostream>
#include<memory.h>
#define ll long long
#define N 10005
#define inf 0x3f3f3f3f3f3f3f3fll
using namespace std;
struct edge{
int e,next,cnt;
ll q;
}ed[N*500];
ll dis[N];
int A,B,n,i,j,len,k,c,ne=0,a[N],city[N],que[N],inq[N],b[N],last[N];
void add(int s,int e,ll q,int cnt)
{
ed[++ne].e=e;ed[ne].q=q;ed[ne].cnt=cnt;
ed[ne].next=a[s];a[s]=ne;
}
void spfa()
{
int head,tail,hh,tt,get,j;
head=tail=hh=tt=1;
for (i=0;i<=1000;i++) inq[i]=0,dis[i]=inf,city[i]=inf;
inq[A]=1;que[1]=A;dis[A]=0;city[A]=0;
while (hh<=tt)
{
get=que[head++];hh++;
if (head>10000) head=1;
for (j=a[get];j;j=ed[j].next)
if (dis[get]+ed[j].q<dis[ed[j].e]||(dis[get]+ed[j].q==dis[ed[j].e]&&city[get]+ed[j].cnt<city[ed[j].e]))
{
last[ed[j].e]=get;
dis[ed[j].e]=dis[get]+ed[j].q;city[ed[j].e]=city[get]+ed[j].cnt;
if (!inq[ed[j].e])
{
tail++;tt++;
if (tail>10000) tail=1;
que[tail]=ed[j].e;inq[ed[j].e]=1;
}
}
inq[get]=0;
}
}
int main()
{
// freopen("3889.in","r",stdin);
// freopen("my.out","w",stdout);
scanf("%d%d%d",&A,&B,&n);
memset(a,0,sizeof(a));
for (i=1;i<=n;i++)
{
scanf("%d%d",&c,&len);
for (j=1;j<=len;j++) scanf("%d",&b[j]);
for (j=1;j<=len;j++)
for (k=j+1;k<=len;k++)
add(b[j],b[k],(ll)c,k-j);
}
spfa();
if (dis[B]==inf) puts("-1 -1");else if (A==B) puts("0 1");else printf("%I64d %d\n",dis[B],city[B]);
j=B;
// while (j!=A) printf("%d ",dis[last[j]]),j=last[j];
}