11-1 noip模擬 第二題 SPFA+狀壓dp
阿新 • • 發佈:2019-02-15
#include #include #include #include using namespace std; struct edge{ long long y,l,z; }f[50010*2]; long long i,j,g[10010],n,m,k,t,dis[17][10010],T,d[16],as,at; bool v[10010]; long long S,F[20][140000]; void spfa(long long st,long long it){ long long i,j,k,l,r,q[100100]; l=0;r=1; q[r]=st; memset(dis[it],78,sizeof dis[it]); memset(v,0,sizeof v); dis[it][st]=0; while(l!=r){ l++; if(l==100000)l=1; k=g[q[l]]; while(k){ if(dis[it][f[k].y]>dis[it][q[l]]+f[k].z){ dis[it][f[k].y]=dis[it][q[l]]+f[k].z; if(v[f[k].y]==0){ v[f[k].y]=1; r++; if(r==100000)r=1; q[r]=f[k].y; } } k=f[k].l; } v[q[l]]=0; } } long long count(long long k){ long long u=k,i=0; while(u){ i+=u%2; u/=2; } return i; } int main(){ scanf("%lld%lld%lld%lld",&n,&m,&k,&t); for(i=1;i<=m;i++){ long long x,y,w; scanf("%lld%lld%lld",&x,&y,&w); f[++T].y=y; f[T].l=g[x]; g[x]=T; f[T].z=w; f[++T].y=x; f[T].l=g[y]; g[y]=T; f[T].z=w; } for(i=1;i<=k;i++){ long long _k; scanf("%lld",&_k); spfa(_k,i); d[i]=_k; } spfa(1,0);spfa(n,k+1); memset(v,0,sizeof v); as=-1;at=(long long)2100000000*5;d[0]=1;d[k+1]=n; memset(F,255,sizeof F); for(i=1;i<=k+1;i++){ F[i][ (1 << ( (i+1) -1))+1]= dis[0][d[i]]; } F[0][1]=0; for(S=1;S<=(1 << 17)-1;S++){ for(i=0;i<=k+1;i++){ if(( ( S >> (i+1-1) )& 1 )== 1){ for(j=0;j<=k+1;j++){ if(j!=i && ((S >> j) & 1 ==1 )&&F[j][S- (1 << i)]!=-1){ if(F[i][S]==-1||F[i][S]>F[j][S- (1 << i)]+dis[j][d[i]])F[i][S]=F[j][S- (1 << i)]+dis[j][d[i]]; } } } } } as=-1; for(S=(1 <<( k+1 )); S<=(1<<17)-1;S++) if((S >> (k+1) )& 1==1&& S % 2 == 1 ){ long long y=count(S); y-=2; if(y>=as){ j=(long long)2100000000*5; for(i=1;i<=k+1;i++){ if(F[i][S]!=-1)j=min(j,F[i][S]+dis[i][d[0]]); } if(j<=t){ if(y==as)at=min(j,at);else at=j; as=y; } } } if(as==-1)printf("-1");else printf("%lld %lld",as,at); return 0; }