本以为是个二进制分组傻逼题https://www.cnblogs.com/Gloid/p/9545753.html,实际上有神仙的一个log做法https://www.cnblogs.com/asuldb/p/10721251.html。下面代码是二进制分组的。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<queue> using namespace std; #define ll long long #define N 100010 #define M 500010 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,k,p[N],a[N],t; ll d[N]; bool flag[N]; struct data{int to,nxt,len; }edge[M]; void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;} struct data2 { int x;ll d; bool operator <(const data2&a) const { return d>a.d; } }; priority_queue<data2> q; void dijkstra() { memset(flag,0,sizeof(flag)); for (;;) { while (!q.empty()&&flag[q.top().x]) q.pop(); if (q.empty()) break; data2 x=q.top();q.pop(); flag[x.x]=1; for (int i=p[x.x];i;i=edge[i].nxt) if (x.d+edge[i].len<d[edge[i].to]) { d[edge[i].to]=x.d+edge[i].len; q.push((data2){edge[i].to,d[edge[i].to]}); } } } int main() { #ifndef ONLINE_JUDGE freopen("bzoj5506.in","r",stdin); freopen("bzoj5506.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif int T=read(); while (T--) { n=read(),m=read(),k=read(); memset(p,0,sizeof(p));t=0; for (int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); addedge(x,y,z); } for (int i=1;i<=k;i++) a[i]=read(); ll ans=10000000000000000ll; for (int _=18;~_;_--) { while (!q.empty()) q.pop(); memset(d,42,sizeof(d)); for (int i=1;i<=k;i++) if (a[i]&(1<<_)) d[a[i]]=0,q.push((data2){a[i],0}); dijkstra(); for (int i=1;i<=k;i++) if (!(a[i]&(1<<_))) ans=min(ans,d[a[i]]); while (!q.empty()) q.pop(); memset(d,42,sizeof(d)); for (int i=1;i<=k;i++) if (!(a[i]&(1<<_))) d[a[i]]=0,q.push((data2){a[i],0}); dijkstra(); for (int i=1;i<=k;i++) if (a[i]&(1<<_)) ans=min(ans,d[a[i]]); } cout<<ans<<endl; } return 0; }
BZOJ5506 GXOI/GZOI2019旅行者(最短路)
原文:https://www.cnblogs.com/Gloid/p/10725368.html